Kotlin比Java更年輕,但它是一個非常有前途的編程語言,它的社區不斷增長。 每個人都在談論它,并說它很酷。 但為什么這么特別?
我們準備了一系列文章,分享我們在Kotlin開發Android應用程序的經驗。 我們將討論Kotlin與Java在語法,可用性,UI性能和異步性方面的區別,以便您可以決定哪種語言最適合您。
讓我們從一些基本的語法差異開始。 這是第一個:
1. 使用Kotlin,你可以用更少的代碼做更多
Kotlin的一個主要優點是它的簡潔。 你用更少的代碼獲得更多的功能。 而你寫的代碼越少,你犯的錯誤就越少。 這很簡單。 讓
我們看看Kotlin的基礎知識,從類開始。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
public final class Person { private String name; private int age; private float height; public Person(String name, int age, float height) { this .name = name; this .age = age; this .height = height; } public Person(String name, int age) { this .name = name; this .age = age; this .height = 1 .8f; } public String getName() { return name; } public void setName(String name) { this .name = name; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } public float getHeight() { return height; } public void setHeight( float height) { this .height = height; } @Override public String toString() { return "Person{" + "name='" + name + '\ '' + ", age=" + age + ", height=" + height + '}' ; } @Override public boolean equals(Object o) { if ( this == o) return true ; if (o == null || getClass() != o.getClass()) return false ; Person person = (Person) o; if (age != person.age) return false ; if (Float.compare(person.height, height) != 0 ) return false ; return name != null ? name.equals(person.name) : person.name == null } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0 ; result = 31 * result + age; result = 31 * result + (height != + 0 .0f ? Float.floatToIntBits(height) : 0 ); return result; } } |
上面是一個通常的Java類。 它做的不多。 它只包含一些數據。 但是,當你意識到它給表帶來的不足時,看看這段代碼有多大是很痛苦的。 為了鼓勵你,我們會給你一個等同的類寫在Kotlin。
1
2
3
|
data class Person(var name: String, var age: Int, var height: Float = 1 .8f) |
是的,你會為你的數據類自動獲取需要的getters,setters,equals(),hashcode(),toString()和copy()函數! 當然,你可以輕松地重寫這些函數,但在大多數情況下,只需聲明類及其屬性就足夠了。
這正是我們的意思,當我們說Kotlin簡潔。
2. 你可以避免 NullPointerException
現在我們想提醒你在許多編程語言中最大的痛苦 - 空指針異常。 我們幾乎不能想象自從托尼·霍爾在1965年發明它之后,有多少開發者遭受了空指針,同時試圖使事情更簡單一些。
可悲的是,我們不能及時回來,防止Tony犯這個錯誤。 但是使用Kotlin,我們現在可以輕松地轉義NullPointerException。
1
2
3
|
val person: Person? = null ... person?.name = "John" |
如果變量是可空的,編譯器將不允許你訪問它沒有適當的檢查。 Kotlin強迫你使用? 運算符。 這可以防止應用程序自動崩潰。
它如何在引擎蓋下工作? 讓我們回顧一下生成的字節碼。
1
2
3
4
5
6
7
8
9
10
|
L2 LINENUMBER 18 L2 ALOAD 3 DUP IFNULL L3 LDC "John" INVOKEVIRTUAL igalata/com/kotlinexample/Person.setName (Ljava/lang/String;)V GOTO L4 L3 POP |
正如你所看到的,我們在這里有相同的空檢查。 JetBrains的開發人員(創建Kotlin)知道每次檢查我們的變量是避免NullPointerException的唯一方法。 但他們也知道Android開發人員不想在他們的項目中處理NullPointerException。 他們可能想:“為什么不自動生成這個檢查如果變量是可空的?
JetBrains的開發人員只是這樣,讓我們的生活更容易了!
3. 你可以擺脫util類
讓我們來討論一下有關使用util類的丑陋事情。 你有沒有一個項目沒有他們? 我們幾乎不記得這一切。 Kotlin有一個聰明的解決方案 - 擴展功能 - 幫助你擺脫所有的util類一勞永逸。
擴展函數幾乎是一個通常的Kotlin函數。 但是當你聲明它,你需要指定的實例將具有擴展功能的類。
fun Context.toast(text: String) = Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
注意'this',我們作為參數傳遞給makeText()方法? 它不是類的一個實例,我們聲明這個函數,而是一個Context實例。 現在你可以直接從你的Activity或任何其他Context實例調用這個函數。 例如:
1
|
toast( "Hi" ) |
你應該記住,擴展函數不以任何方式修改它擴展的類。 那么它如何工作而不改變原來的類? 讓我們再次看到字節碼。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public final toast(Landroid/content/Context;Ljava/lang/String;)V @Lorg /jetbrains/annotations/NotNull;() // invisible, parameter 0 @Lorg /jetbrains/annotations/NotNull;() // invisible, parameter 1 L0 ALOAD 1 LDC "$receiver" INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V ALOAD 2 LDC "text" INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V L1 LINENUMBER 31 L1 ALOAD 1 ALOAD 2 CHECKCAST java/lang/CharSequence ICONST_0 INVOKESTATIC android/widget/Toast.makeText (Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; INVOKEVIRTUAL android/widget/Toast.show ()V L2 LINENUMBER 32 L2 RETURN L3 LOCALVARIABLE this Ligalata/com/kotlinexample/MainActivity; L0 L3 0 LOCALVARIABLE $receiver Landroid/content/Context; L0 L3 1 LOCALVARIABLE text Ljava/lang/String; L0 L3 2 MAXSTACK = 3 MAXLOCALS = 3 |
哈! 您的函數隱式接收它作為第一個參數擴展的類的實例。 因此,在字節碼中,對函數體中“this”的任何訪問都將替換為對第一個參數的訪問。 沒有魔法真的。 您可以在項目的任何位置使用此函數。
時間刪除你的util包!
4. 你可以忘記視圖綁定
你還記得findViewById()method()嗎? 我們相信你不喜歡它。 我們也不是。 此外,我們不想為我們需要訪問的每個視圖聲明變量和Butterknife注釋。
你可以忘記與Kotlin Android Extensions的視圖綁定。 不再需要創建變量和綁定視圖。 您可以使用在xml布局中聲明的標識符直接訪問您的視圖。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class MainActivity extends AppCompatActivity { @Override protected void onCreate( @Nullable Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); final TextView text = (TextView) findViewById(R.id.text); button.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { text.setText( "You've clicked a button" ); } }); } } class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { super .onCreate(savedInstanceState, persistentState) setContentView(R.layout.activity_main) button.setOnClickListener { text.text = "You've clicked a button" } } } |
這太簡單了,不是嗎?
基本上,findViewById()方法仍在使用中。 但是沒有必要自己寫。 Kotlin會為你做。
當您使用Android擴展時,findCachedViewById()函數和HashMap實例將會自動生成。 每次通過其標識符訪問您的視圖將被一個新的函數調用替換。 如果是第一次訪問視圖,此函數將調用通常的findViewById()函數,并將接收的視圖添加到HashMap中,以便在下次訪問視圖時從中檢索視圖。
5. 你可以更容易地使用集合
讓我們談談Kotlin的集合。 因為我們經常需要使用數據模型集合執行困難的操作。 例如,我們可能有一個學生名單,我們需要從中檢索三個A級成績的學生和兩個B成績的學生。
看看Kotlin的解決方案:
1
2
3
4
5
|
var students = listOf(Student( "John" , 0 ), Student( "Julia" , 2 ), Student( "Matt" , 1 ), Student( "Katie" , 0 ), Student( "Dan" , 0 )) var firstList = students.filter { it.mark == 0 }.take( 3 ) var secondList = students.filter { it.mark == 1 }.take( 2 ) |
下面是我們如何解決Java中的同樣的問題:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
ArrayList<Student> students = new ArrayList<Student>() {{ add( new Student( "John" , 0 )); add( new Student( "Julia" , 2 )); add( new Student( "Matt" , 1 )); add( new Student( "Katie" , 0 )); add( new Student( "Dan" , 0 )); }}; ArrayList<Student> firstList = new ArrayList<>(); ArrayList<Student> secondList = new ArrayList<>(); for (Student student: students) { boolean isFirstFilled = firstList.size() >= 3 ; boolean isSecondFilled = secondList.size() >= 2 ; if (isFirstFilled && isSecondFilled) break ; int mark = student.getMark(); if (mark == 0 && !isFirstFilled) { firstList.add(student); } else if (mark == 1 && !isSecondFilled) { secondList.add(student); } } |
這只是一個小例子,說明如何在Kotlin和Java中使用集合,但你可以看到差別! 你能想象如果我們處理一個大項目的集合,Kotlin會有什么區別嗎?
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!