快速上手kotlin
首先我們先了解一下什麼是kotiln?
Kotlin 是一個基於 JVM 的新的程式語言,由 JetBrains 開發。
Kotlin可以編譯成Java位元組碼,也可以編譯成JavaScript,方便在沒有JVM的裝置上執行。
JetBrains,作為目前廣受歡迎的Java IDE IntelliJ 的提供商,在 Apache 許可下已經開源其Kotlin 程式語言。
Kotlin已正式成為Android官方支援開發語言。
那麼kotiln與Java相比有什麼優勢呢?
Kotlin編譯為JVM位元組碼或JavaScript ,像Java一樣,Bytecode也是Kotlin程式的編譯格式。 位元組碼錶示程式設計程式碼,一旦編譯,就通過虛擬機器而不是計算機的處理器執行。 通過使用這種方法,一旦編譯並執行虛擬機器,原始碼就可以在任何平臺上執行。 一旦kotlin程式被轉換為位元組碼,它可以通過網路傳輸並由JVM(Java虛擬機器)執行。
Kotlin程式可以使用所有現有的Java框架和庫 ,是的,Kotlin程式可以使用所有現有的Java框架和庫,甚至依賴於註釋處理的高階框架也是如此。關於kotlin語言的主要重點是它可以輕鬆地與Maven和其他構建系統整合。Kotlin可以輕鬆學習,平易近人。通過簡單的閱讀語言參考可以輕鬆學習。語言乾淨直觀(易於使用和理解)。Kotlin看起來很像Scala,但更簡單。Kotlin是開放原始碼,沒有收費。
將Java自動轉換為Kotlin - JetBrains將IntelliJ集成了一個新功能,將Java轉換為Kotlin,節省了大量的時間。而且它也節省了我們重新編寫世代程式碼。
Kotlin的空安全性很好 - 現在擺脫NullPointerExceptions。這種型別的系統幫助我們避免空指標異常。在Kotlin系統中,系統只拒絕編譯嘗試分配或返回null的程式碼考慮以下示例 -
程式碼審查不是問題 - 科特林更注重可讀性的語法,所以程式碼審查不是一個問題,它們仍然可以由那些不熟悉語言的團隊成員完成。
最後讓我們來看看Kotlin 基本語法
先說個學習Kotlin語法的小竅門,將程式碼用Java寫好,然後Code/Conver Java File to Kotlin File轉換成Kotlin程式碼,或者將Java程式碼複製到Kotlin檔案會提示轉換也是挺方便的,比較差異很容易就能理解了,一開始難免不適應習慣後相信你一定會喜歡上Kotlin
Kotlin定義
忘掉Java的那一套寫法不然會很不適應的,Kotlin有自己的特性不該被Java的思維所束縛。在Kotlin中常量用val宣告,變數用var宣告,關鍵字在前面,型別以冒號:隔開在後面,也可以省略直接賦值,型別後帶問號?表示可為空型別(預設空安全)。常量val延遲載入by lazy{},預設執行緒安全關閉執行緒安全lazy(LazyThreadSafetyMode.NONE){},變數var延遲載入late init。
//常量陣列int[][][] arrs = new int[3][2][1];
val arrs = Array(3) { Array(2) { IntArray(1) } }
//空安全變數
var str: String = "hello"
var str1 = "word"
//可為空字串變數
var str2: String? = null
條件
if…else 正常使用,不過移除了switch用更強大的when替代,when子式可以是常量、變數、返回數值的表示式、返回Boolean值的表示式,強大到用來替換if…else if
// 測試值 x = 0, -1, 1, 2, 3, 6, 10
var x = 10
when (x) {
//常量
2 -> println("等於2")
//數值表示式
if (x > 0)
1
else
-1 -> println("大於0並等於1,或小於0並等於-1")
//Boolean型別表示式
in 1..5 -> println("範圍匹配1-5")
!in 6..9 -> println("不是6-9")
is Int -> println("型別判斷")
else -> println("else")
}
// 代替if...else if
when{
x > 6 && x <= 10 -> println("大於6小於等於10")
x < 6 -> println("小於6")
else -> println("else")
}
迴圈
while 和 do…while 同Java並無區別,for則有很大改變並多出了幾個變種
val list = arrayListOf("aa", "bb", "cc")
//遞增for (int i = 0; i < list.size(); i++)
for (i in list.indices) {
print(list[i])
}
//遞增for (int i = 2; i < list.size(); i++)
for (i in 2..list.size-1) {
print(list[i])
}
//遞減for (int i = list.size() - 1; i >= 0; i--)
for (i in list.size - 1 downTo 0) {
print(list[i])
}
//操作列表內的物件
for (item in list) {
print(item)
}
//加強版
for((i, item) in list.witnIndex()) {
print(list[i])
print(item)
}
//變種版
list.forEach {
print(it)
}
list.forEach {
print(it)
}
list.forEachIndexed { i, s ->
print(list[i])
print(s)
}
list.forEachIndexed(object :(Int,String) -> Unit{
override fun invoke(i: Int, s: String) {
print(list[i])
print(s)
}
})
萬能的冒號
在Kotlin中冒號:用萬能來稱呼絕不為過。常量變數的型別宣告,函式的返回值,類的繼承都需要它
//val表示常量var表示變數宣告
val name: String = "ljz"
//省略型別說明
var age = "23"
//fun表示函式
fun getName(): String{
return "ljz"
}
//類繼承
class UserList<E>(): ArrayList<E>() {
//...
}
除此之外還有一個特別的地方也需要它,使用Java類的時候。Kotlin最終還是會編譯成Java位元組碼,使用到Java類是必然的,在Kotlin語法如下
val intent = Intent(this, MainActivity::class.java)
類名::class.java沒有為什麼就這麼寫記著就是
我是誰的@
除了冒號另一個重要符號@,想必用到內部類和匿名內部類的地方一定很多,再加上支援lambda語法,沒有它誰告訴你this和return指的是哪一個
class User {
inner class State{
fun getUser(): User{
//返回User
return [email protected]
}
fun getState(): State{
//返回State
return [email protected]
}
}
}
偷懶的方法
- Kotlin特色
Java的getter/setter方法自動轉換成屬性,對應到Kotlin屬性的呼叫
public class User {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
反之Kotlin的屬性自動生成Java的getter/setter方法,方便在Java中呼叫,同樣的定義在Kotlin中
class User {
var name: String? = null
var age: String? = null
}
這樣一個Java類在Kotlin中只需這樣呼叫
val user = User()
//賦值
user.name = "ljz"
user.age = "23"
//取值
val name = user.name
val age = user.age
我們的getter/setter方法有時不會這麼簡單,這就需要自定義getter/setter了,另起一行設定get()/set(value)方法,實現一個Java中常用的單例,這裡只為了展示,單例在Kotlin有更簡單的方法實現,只要在 package 級別建立一個 object 即可
class User {
companion object {
@Volatile
var instance: User? = null
get() {
if (field == null) {
synchronized(User::class.java) {
if (field == null)
field = User()
}
}
return field
}
}
var name: String? = null
var age: String? = null
}
自定義getter/setter重點在field,跟我們熟悉Java的this指代當前類一樣,field指代當前引數,直接使用引數名instance代替不會報錯但單例就沒效果了
- 字串模板
在Java中拼接字串的程式碼可讀性都很差,在Kotlin字串拼接變得非常簡潔,只需用$後面加上引數名,複雜的引數要加上{}
val user = User()
//賦值
user.name = "ljz"
user.age = "23"
//取值
val name = user.name
val age = user.age
var userInfo = "name:${user.name}, age:$age"
//輸出結果:name:ljz, age:23
- lambda
一開始覺得lambda很高階完全看不懂,其實很簡單的就是把介面名、方法名和引數型別省掉不寫再加個->罷了,明白這點了很好理解。
// 無引數無返回值
Thread(Runnable {
sleep(1000)
}).start()
// 單引數不帶返回值
view.setOnClickListener { v ->
Log.e("tag", "${v.tag}")
}
// 多引數帶返回值
view.setOnKeyListener(View.OnKeyListener { v, keyCode, event ->
Log.e("tag", "keyCode$keyCode, ${event.keyCode}")
if (event.keyCode == KeyEvent.KEYCODE_BACK)
[email protected] true
false
})
新面孔
- 延遲載入
- 流程控制
空判斷
Kotlin的空安全設計對於宣告可為空的引數,在使用時要進行空判斷處理,有兩種處理方式,欄位後加!!像Java一樣丟擲空異常,另一種欄位後加?可不做處理返回值為 null或配合?:做空判斷處理
//型別後面加?表示可為空
var age: String? = "23"
//丟擲空指標異常
val ages = age!!.toInt()
//不做處理返回 null
val ages1 = age?.toInt()
//age為空返回-1
val ages2 = age?.toInt() ?: -1
注意事項
內部類和引數預設為public,而在Java中為 default 即在同一個包中可見
類預設為不可繼承(final),想要可被繼承要宣告為open或abstract
取消了static關鍵字,靜態方法和引數統一寫在companion object塊
internal模組內可見,inner內部類
總結
以上僅是對使用頻率較高的語法總結,學會基本可以閱讀Kotlin程式碼,遇到點問題Google速查一下,至於智慧轉換、型別推導之類的不用說使用後喜歡自然就會了。當然這只是kotlin的基本語法,方便Java快速熟悉kotlin,深入學習還請閱讀相關資料。