Kotlin VS Java:基本語法差異
阿新 • • 發佈:2019-02-18
Kotlin比Java更年輕,但它是一個非常有前途的程式語言,它的社群不斷增長。 每個人都在談論它,並說它很酷。 但為什麼這麼特別?
我們準備了一系列文章,分享我們在Kotlin開發Android應用程式的經驗。 我們將討論Kotlin與Java在語法,可用性,UI效能和非同步性方面的區別,以便您可以決定哪種語言最適合您。
讓我們從一些基本的語法差異開始。 這是第一個:
這正是我們的意思,當我們說Kotlin簡潔。
2. 你可以避免
現在我們想提醒你在許多程式語言中最大的痛苦 - 空指標異常。 我們幾乎不能想象自從託尼·霍爾在1965年發明它之後,有多少開發者遭受了空指標,同時試圖使事情更簡單一些。
可悲的是,我們不能及時回來,防止Tony犯這個錯誤。 但是使用Kotlin,我們現在可以輕鬆地轉義NullPointerException。
它如何在引擎蓋下工作? 讓我們回顧一下生成的位元組碼。
JetBrains的開發人員只是這樣,讓我們的生活更容易了!
擴充套件函式幾乎是一個通常的Kotlin函式。 但是當你宣告它,你需要指定的例項將具有擴充套件功能的類。
時間刪除你的util包!
你可以忘記與Kotlin Android Extensions的檢視繫結。 不再需要建立變數和繫結檢視。 您可以使用在xml佈局中宣告的識別符號直接訪問您的檢視。
基本上,findViewById()方法仍在使用中。 但是沒有必要自己寫。 Kotlin會為你做。
當您使用Android擴充套件時,findCachedViewById()函式和HashMap例項將會自動生成。 每次通過其識別符號訪問您的檢視將被一個新的函式呼叫替換。 如果是第一次訪問檢視,此函式將呼叫通常的findViewById()函式,並將接收的檢視新增到HashMap中,以便在下次訪問檢視時從中檢索檢視。
看看Kotlin的解決方案:
我們準備了一系列文章,分享我們在Kotlin開發Android應用程式的經驗。 我們將討論Kotlin與Java在語法,可用性,UI效能和非同步性方面的區別,以便您可以決定哪種語言最適合您。
讓我們從一些基本的語法差異開始。 這是第一個:
1. 使用Kotlin,你可以用更少的程式碼做更多
Kotlin的一個主要優點是它的簡潔。 你用更少的程式碼獲得更多的功能。 而你寫的程式碼越少,你犯的錯誤就越少。 這很簡單。 讓我們看看Kotlin的基礎知識,從類開始。
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。
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。
val person: Person? = null
...
person?.name = "John"
如果變數是可空的,編譯器將不允許你訪問它沒有適當的檢查。 Kotlin強迫你使用? 運算子。 這可以防止應用程式自動崩潰。它如何在引擎蓋下工作? 讓我們回顧一下生成的位元組碼。
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例項呼叫這個函式。 例如:
toast("Hi")
你應該記住,擴充套件函式不以任何方式修改它擴充套件的類。 那麼它如何工作而不改變原來的類? 讓我們再次看到位元組碼。
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佈局中宣告的識別符號直接訪問您的檢視。
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的解決方案:
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中的同樣的問題:
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會有什麼區別嗎?