簡介
Kotlin基本語法對(duì)比
本篇文章主要是為了方便Android開發(fā)者從Java轉(zhuǎn)到Kotlin初期的迷茫,提供兩種語言基礎(chǔ)語法的對(duì)比,方便理解
1 聲明(常量與變量)
在Kotlin中,聲明變量有兩個(gè)關(guān)鍵字,它們是val與var
var:可重新賦值的變量使用var關(guān)鍵字,代表著變量(可讀可寫)
val:只能為其賦值一次的變量使用val關(guān)鍵字,代表變量(只讀),跟final有略微不同
通過代碼來對(duì)比
Kotlin:
val a: Int = 1 // 立即賦值
val b = 2 // 自動(dòng)推斷出 `Int` 類型
var c = 0 // 自動(dòng)推斷出 `Int` 類型
c = 1
Java:
final int a = 1;
final int b = 2;
int c;
c = 3;
簡單的對(duì)比可以比較清晰的看出來:
var:定義變量的時(shí)候不帶final
val:相當(dāng)于定義變量的時(shí)候帶final,但是跟final又有略微的不同,到底有什么區(qū)別呢?請(qǐng)看接下來的"屬性與字段"
1.1 屬性與字段
首先我們需要區(qū)分一下屬性和字段
Kotlin中聲明的變量,都是屬性
Java中聲明的變量,都是字段
接下來我們看看在Kotlin中聲明一個(gè)變量的完整步驟來更好的理解:
class KotlinTest {
val a = 1
var b = 2//屬性
}
通過Decompile轉(zhuǎn)換成Java看一下具體的操作
public final class KotlinTest {
private final int a = 1;
private int b = 2; //第一部分創(chuàng)建字段
public final int getA() {
return this.a;
}
//第二部分創(chuàng)建get()
public final int getB() {
return this.b;
}
//第三部分創(chuàng)建set()
public final void setB(int var1) {
this.b = var1;
}
}
小結(jié):
-
val聲明的是屬性,final聲明的是字段 - Kotlin中屬性的聲明 = Java中字段聲明 + get() + set()
- 而被
val聲明的屬性是沒有set() - 盡量用
val,為什么要設(shè)置這兩個(gè)類型聲明,因?yàn)楫?dāng)變量不可變的時(shí)候,建議使用final標(biāo)記,但是很多同學(xué)在寫的時(shí)候覺得麻煩,沒省略了final,為了代碼的安全性,設(shè)置了val,省略了寫final的步驟,更適合讓同學(xué)們使用
1.2 幕后字段 field
在 Kotlin 類中不能直接聲明字段,聲明的是屬性。而屬性是不能保存狀態(tài)的,只有字段才能保存狀態(tài),所以Kotlin在屬性聲明的時(shí)候,會(huì)默認(rèn)創(chuàng)建一個(gè)字段,叫做“幕后字段”。
var counter = 0 // 注意:這個(gè)初始器直接為幕后字段賦值
set(value) {
if (value >= 0) field = value// 注意:并不是直接賦值給counter,而是賦值給幕后字段
}
1.3 延時(shí)屬性 lateinit
一般地,屬性聲明為非空類型必須在構(gòu)造函數(shù)中初始化。比如:
var a: Person = Person()
但是我們?cè)谑褂肑ava的時(shí)候,經(jīng)常是創(chuàng)建一個(gè)變量,并不會(huì)立即給賦值,比如:
private Person p;
這種情況下,你可以用lateinit修飾符標(biāo)記該屬性:
lateinit var a: Person
在初始化前訪問一個(gè)lateinit屬性會(huì)拋出一個(gè)特定異常,該異常明確標(biāo)識(shí)該屬性被訪問及它沒有初始化的事實(shí)。要檢測(cè)一個(gè) lateinit var 是否已經(jīng)初始化過,請(qǐng)?jiān)谠搶傩缘囊蒙鲜褂?.isInitialized:
if (::a.isInitialized) {
println(a.name)
}
使用lateinit修飾符的時(shí)候,需要注意以下幾點(diǎn):
- 該修飾符只能用于在類體中的屬性
- 只能修飾var,不能修飾val
更多l(xiāng)ateinit相關(guān)請(qǐng)點(diǎn)擊查看
更多屬性與字段相關(guān)請(qǐng)查看
2 類型
Kotlin:
val a: Int = 1 // 立即賦值
val b = 2 // 自動(dòng)推斷出 `Int` 類型
val c: Int // 如果沒有初始值類型不能省略
c = 3 // 明確賦值
Java:
public final int a = 1;
public final int b = 2;
public final int c = 3;
通過上面的對(duì)比,可以發(fā)現(xiàn)Kotlin與Java之間有以下幾點(diǎn)差別
- 寫法上有區(qū)別:
Kotlin:<屬性名>: <數(shù)據(jù)類型>
Java:<數(shù)據(jù)類型> <屬性名> - Kotlin可以推斷出屬性類型,Java需要必須手動(dòng)設(shè)置
3 空安全
在Java中,最常見的異常就是被稱之為《十億美元的錯(cuò)誤》。就是訪問空引用的成員會(huì)導(dǎo)致空引用異常, NullPointerException 或簡稱 NPE。而Kotlin 的類型系統(tǒng)旨在消除來自代碼空引用的危險(xiǎn)。
3.1 可空類型與非空類型
在Kotlin中,一個(gè)變量想要允許為空,必須加上?
Kotlin:
var a: String = "abc"
a = null // 編譯錯(cuò)誤
var b: String?
b = null // ok
print(b)
val la = a.length // 正確:變量"a"不可能為空,放心使用
val lb = b.length // 錯(cuò)誤:變量"b"可能為空
val lb2 = b?.length //正確:當(dāng)變量"b"為空時(shí),返回null
Java:
public String a = "abc";
a = null; //ok
3.2 空判斷
在條件中檢查null:
Kotlin:
val b: String? = null
val l = if (b != null) b.length else -1
Java:
String b = null;
final int l;
if (b != null){
l = b.length();
}else{
l = -1;
}
空安全的調(diào)用:
Kotlin:
val a = "Kotlin"
val b: String? = null
println(b?.length)
println(a?.length) // 無需安全調(diào)用
//鏈?zhǔn)秸{(diào)用
val name = bob?.department?.head?.name
Java:
final String a = "Kotlin";
final String b = null;
if (b == null){
System.out.print("null");
}else {
System.out.print(b.length());
}
System.out.println(a.length());
//鏈?zhǔn)秸{(diào)用
final String name;
if (bob != null) {
if (department != null) {
if (head != null) {
name = bob.department.head.name;
}
}
}
小結(jié):
- 在Kotlin中,所有允許為null的變量必須添加
? - 當(dāng)調(diào)用的時(shí)候,對(duì)象為null的時(shí)候,會(huì)返回null,而不是報(bào)NPE錯(cuò)誤
- 在鏈?zhǔn)秸{(diào)用中,如果任意一個(gè)屬性(環(huán)節(jié))為空,這個(gè)鏈?zhǔn)秸{(diào)用就會(huì)返回 null。
4 總結(jié)
本文只是簡單的對(duì)比了Kotlin與Java的語法上的區(qū)別,然后Kotlin并不是這么簡單,需要深入學(xué)習(xí)才能掌握。希望對(duì)大家有所幫助,如果文章有不足之處,請(qǐng)不吝指出,謝謝。