1 概述
這篇文章首先會介紹Kotlin的特點,接着介紹Kotlin與Java的語法比較。
2 Kotlin特點
- 一門現代化的編程語言
- 可開發跨平台應用,web,Socket,安卓,js,NativeApp等
- 靜態編程語言,性能基本與原聲Java相當
- 100%兼容Java(說是兼容但實際上有些坑,可以戳這里看看)
- 簡潔:跟Java相比真的是簡潔很多,語法糖特別舒服
- 安全:徹底解決寫Java基本上都會遇到的著名的NullPointerException問題,結合編譯器可以在編譯截斷發現幾乎所有可能存在NPE問題的代碼
- 互操作性:基於JVM,可以直接拿現有的Java庫用
- 工具友好:和JetBrains的IDE結合簡直舒服得不要不要的
- 支持函數式編程:比如Lambda表達式
- 支持協程:協程像是非常輕量級的縣城,協程將復雜性放入庫來簡化異步編程,邏輯可以在協程中順序表達,底層庫負責解決異步性,很重要的一點是協程掛起不會阻塞其他線程。官方一個demo是開啟10w個協程:

- 支持擴展函數:類似C#,能夠擴展一個類的新功能而無需繼承類或者使用裝飾者這樣的設計模式,Kotlin支持擴展函數和擴展屬性
- 泛型:當然Java也支持泛型,但是Kotlin比Java支持得更好
- 不依賴XML
下面進入Kotlin的語法部分。
3 基本語法
- 無
;結尾 println()代替System.out.println();- 輸出語句中使用
$變量名代替Java中的+變量名,比如println("age:$age")而不是System.out.println("age:"+age) - 三引號(三個雙引號連在一起)中的字符串不會進行轉義
4 變量與常量
var聲明變量val聲明常量- 可以在
var/val后面加上類型,比如val a:Int

如上圖提示val不能被賦值,提示改為var。val類似與Java中的final,雖然val引用自身不可變,但是指向的對象是可以改變的。
val只能進行唯一一次初始化,如果編譯器能確保只有唯一一條初始化語句被執行,可以根據條件進行不同的初始化操作:
val a:Int
if (4>3)
{
a = 9
}
else
{
a = 10
}
5 表達式和語句
Java中所有的控制結構都是語句,在Kotlin中除了三大循環(while,for,do while)外,大多數控制結構都是表達式。比如if是表達式而不是語句。也就是說,if有值而不像Java里面一樣沒有值(語句)。
例子:
var a = if (3>2) 3 else 2
fun main()
{
var a = max(4,9)
}
fun max(a:Int,b:Int): Int = if(a>b) a else b
6 枚舉
使用enum class而不是Java中的enum:
fun main()
{
val months = Months.May
println(months.days)
}
enum class Months(val days:Int)
{
May(31),
Jun(30)
}
7 when
when相當於Java中的switch:
fun main()
{
val months = Months.May
when(months)
{
Months.May -> print("May")
Months.Jun -> print("June")
}
}
enum class Months(val days:Int)
{
May(31),
Jun(30),;
}
使用->進行了簡化。
8 循環
8.1 while與do while
與Java一樣。
8.2 for
使用..表示區間,在i前面沒有類型:
for (i in 1..100)
print(i)
注意區間是兩邊都包含的,也就是1..100表示i從1循環到100。
使用下標迭代:
val arr = arrayListOf("1111","2222","333")
for ((i,e) in arr.withIndex())
println("$i = $e")
輸出:
0 = 1111
1 = 2222
2 = 333
9 類
9.1 構造方法
class Person(val name:String)
不需要像Java一樣this.xxx=xxx。
9.2 getter/setter
因為val代表常量,而var代表變量,setter是用於改變值的,因此,使用var聲明的屬性具有getter與setter,使用val聲明的屬性只有getter。
Kotlin沒有提供直接操縱getter與setter的方式,通過使用.屬性名進行修改屬性或者獲取屬性:
class Person
{
var name = ""
val id = ""
}
var person = Person()
person.name="111"
person.id="222" //編譯不通過,id為val不可變
9.3 自定義getter/setter
在相應的屬性后面加上get/set即可自定義getter/setter:
class Person
{
var name=""
get()
{
return "name"+field
}
var id=""
set(id)
{
field = id
}
}
在get/set中使用field表示字段,比如在上面例子中的get中,field表示name,而在下面的set中,field表示自己的id,=后面是參數的id。
10 異常
10.1 拋出異常
直接throw,無需new:
val age = 300
if(age !in 1..100)
throw IllegalArgumentException("Out of range:$age")
10.2 try/catch
try
{
throw Exception("exception")
}
catch (e:Exception)
{
e.printStackTrace()
}
10.3 受檢異常與不受檢異常
Java中的異常有兩類:
Unchecked Exception:不受檢異常,可以不進行try/catch處理,包括Runtime Exception及其子類Checked Exception:受檢異常,必須進行try/catch處理或者聲明需要拋出,不屬於不受檢異常的異常都屬於受檢異常
Kotlin不區分兩者,也就是對於Java的受檢異常可以不處理,比如:
fun main()
{
throw IllegalArgumentException("333")
}
可通過編譯,而Java中的
public class Test
{
public static void main(String []args)
{
throw new Exception("111");
}
}
則無法通過編譯。
11 集合類
val arrayList = ArrayList<Int>()
arrayList.add(3)
arrayList.add(9)
arrayList.forEach { t-> println(t) }
val hashSet = hashSetOf<String>()
hashSet.add("2222")
hashSet.add("99999")
hashSet.forEach{t-> println(t)}
val list = listOf(3,5,5)
list.forEach{t-> println(t)}
val map = mapOf("a" to 1,"b" to 2)
map.forEach{(k,v)-> println("$k to $v")}
可以直接使用集合類或者xxxOf創建,遍歷使用forEach與Lambda,Kotlin風格的Lambda使用{}。
12 函數
12.1 基本語法
fun printStr(str:String)
{
println(str)
}
fun add(a:Int):Int
{
return a+3
}
fun聲明函數- 形參類型在形參名稱后
- 返回類型放在最后,前面需要帶
: - 函數不強制放在類中
12.2 默認參數
Java里面沒有默認參數,實現類似功能需要重載去解決,而Kotlin的函數可以具有默認參數:
fun main()
{
println(add())
println(add(1))
println(add(1,2))
}
fun add(a:Int = 3,b:Int = 4):Int = a+b
可以省略的只有在末尾的參數,也就是默認參數從末尾開始確定默認值。
12.3 命名參數
類似Python,調用函數時使用形參名稱與值的方式調用而不是僅僅通過值調用,同時可以結合默認參數省略部分值。
fun main()
{
println(add(b=1))
println(add(b=5,a=9))
}
fun add(a:Int = 3,b:Int = 4):Int = a+b
12.4 可變參數
使用vararg:
fun main()
{
println(add(1,2,3,4))
}
fun add(vararg a:Int):Int = a.sum()
13 頂層函數與頂層屬性
13.1 頂層函數
Kotlin中可以將函數放在代碼文件的頂層,不用附屬於任何類,但仍然是包內作用域,包外需要import,作用類似Java中的靜態函數。
fun add(vararg a:Int):Int = a.sum()
fun main()
{
println(add(1,2,3,4))
}
Java中調用頂層函數時可以使用默認的Kotlin文件名作為默認包去調用,也可以使用@file:JvmName修改調用的包名,比如上面的文件名為Test.kt,則Java中調用的代碼如下:
TestKt.add()
使用注解后:
@file:JvmName("Test")
fun add(vararg a:Int):Int = a.sum
fun main()
{
println(add(1,2,3,4))
}
Java調用方式改變如下:
Test.add()
13.2 頂層屬性
與Java中的靜態屬性類似,有點像全局變量或全局常量,可以使用var,val,const val修飾:
var a = 0
val b = 0
const val c = 0
fun main()
{
println(++a)
println("$b\n$c")
test()
}
fun test()
{
println("$a\n$b\n$c")
}
val與const val的主要區別是:
val實質上相當與Java中的private final staticconst val實質上相當於Java中的public final staticconst相當於@JvmField,也就是說const val a = 0與@JvmField val a = 0等價:
14 參考
1、Kotlin語言的特點和優劣勢
2、Java受檢異常與不受檢異常
3、Kotlin中的getter與setter
4、Kotlin與Java的異同
5、Kotlin之const val與val
