作者介紹:劉高軒,美團點評Android工程師,2年Android開發經驗,現在是美團點評點餐團隊的一員。
前言
本文主要介紹了新晉Android官方開發語言Kotlin的語法基礎和實用特性,並加以簡單的快速實踐,給出了Kotlin相比Java的開發效率優勢,非常適合對Kotlin感興趣的Android開發人員進行閱讀。
本文較長(6000字左右),建議閱讀時間: 30min+
目錄
- 1 背景
- 2 語法速看
- 2.1 變數型別與符號
- 2.2 函式與方法
- 2.3 類與繼承
- 2.4 邏輯語句
- 3 實用特性
- 3.1 空指標安全
- 3.2 擴充套件方法和屬性
- 3.3 簡潔資料類
- 3.4 Anko
- 4 快速實踐
- 4.1 配置AS
- 4.2 Demo
- 5 結語
背景
今年的Google I/O 2017,Kotlin正式成為Android的官方開發語言。這門被稱為“The Swift of Android”的語言(具體對比可參考Swift is like Kotlin),自Jetbrains推出至今已有六年時間,而首個官方穩定版本卻是去年2月才釋出的。也正是從去年開始,Kotlin的使用度迎來了爆炸式的增長,這裡有一張官方的GIF圖可以看出其2016年的發展速度。
Kotlin好處都有啥?誰說對了都給他。作為一個旨在取代Android開發人員基數眾多的Java語言的新興語言,完全與Java老大哥割裂開,那日後的推廣肯定是步履維艱。Kotlin巧妙地作為一個靜態JVM語言誕生,與Java完全相容,又比Java要更加簡潔,同時也處理了讓無數開發者頭疼的NullPointerException問題,顯得很有吸引力。對於一個有經驗的Android開發者來說,學習Kotlin的曲線相當平緩,可以幾乎零成本去改造已有Android專案的部分程式碼。面對這充滿了新特性的語言,誰會不動心呢?
Kotlin語言主要有以下幾個特點:
- 高度相容Java:Kotlin也可以呼叫傳統Java語言的各種類庫。由於最終都是編譯為JVM位元組碼執行,Kotlin可以與Java存在於同一個專案中,互相呼叫。開發者可以部分改造專案中的程式碼,嘗試其新語言特性。官方提供Java程式碼到Kotlin程式碼的轉換工具。開發者可以把現有的Java/Android專案一鍵轉換為Kotlin專案,實現零成本的改造。
- 程式碼簡潔高效:語法精煉,無處不在的型別推斷,自動生成通用方法,支援Lamda表示式,使Kotlin的程式碼行數遠低於傳統Java程式碼。而程式碼量的壓縮,客觀上會提高開發效率。
- 空指標安全:通過符號“?”定義物件的nullable,讓開發者不用為了避免NPE而寫太多防禦性程式碼。
- 函數語言程式設計:支援讓函式作為引數或者返回的高階函式用法,支援流式API,支援擴充套件方法。
2 語法速看
2.1 變數、型別與符號
基礎型別
java中存在int,float,boolean等基礎型別,這些基礎型別在Kotlin裡將全部以物件的形式繼續存在。隨之而來使用上也發生一些變化,有幾點需要注意下:
// Int無法自動轉換為Double, 需要自己先做型別轉換(as Double, toDouble(), 方式很多)
var a: Int = 2
var b: Double = a.toDouble()
// Char不能直接等值於其對應的ASCII碼值,需要型別轉換
var c: Char = 'a'
var ca: Int = c.toInt()複製程式碼
變數宣告
Kotlin中使用var定義變數(和js很像),使用val定義常量(相當於java當中的final)。定義變數時既可以指定型別,也可以不指定,Kotlin支援型別推斷。
var name = "me" // 型別為String
var name: String = "me" // 型別為String
val TAG: String = "KotClassA"複製程式碼
需要注意的是,你不能直接寫一個var num丟在程式碼裡不初始化值,編譯器會無法推斷它的型別
var name // 編譯器報錯
var name: String // 型別為String複製程式碼
行尾標識
與Java中以“;”符號區分每行的結尾不同,Kotlin中不再需要在每行程式碼的結束位置寫“;”。當然如果你一時改不了寫Java時的習慣,IDE也並不會報錯,只會友好地把“;”置灰並下劃線,提示你這是多餘之舉。
型別宣告
Java語言中,“:”符號主要出現於三元運算子“A ? B : C”中,for迴圈時遍歷列表項和switch的每種情形分支。而在Kotlin語言中,“:”被廣泛用於變數型別的定義。
// 定義變數型別
fun common() {
var ka: KClassA
var kb: KClassB
}
// 定義函式的引數和返回值
fun helloStr(str: String): String {
var strHello: String = "hello"
strHello += str
return strHello
}複製程式碼
“:”還被用於宣告類繼承或介面實現。
interface KInterfaceA {
...
}
open class KClassA(n: Int): KInterfaceA {
...
}
class KClassB(n: Int): KClassA(n) {
...
}複製程式碼
此外,如果你想在Kotlin程式碼中使用Java類,也需要用到“:”符號。連續兩個“:”表明對Java類的呼叫。
val intent = Intent(this, MainActivity::class.java)複製程式碼
型別檢測
Java語言中使用instanceof來判斷某變數是否為某型別,而Kotlin中使用更短小更直觀的is來進行型別檢測。
if (num instanceof Double) { ... } // Java程式碼
if (num is Double) { ... } // Kotlin程式碼複製程式碼
字串模板
Java中使用字串模板會比較麻煩,而且不太直觀。而Kotlin裡使用則異常便捷好用。
// Java中字串模板兩種常用形式
String name = "我";
int age = 25;
String.format("%s今年%d歲", name, age);
MessageFormat.format("{0}今年{1}歲", name, age);
// Kotlin中更直觀的字串模板形式
var name = "我"
var age = 25
"${name}今年${age}歲"複製程式碼
2.2 函式與方法
Kotlin中的函式通過關鍵字fun定義的,具體的引數和返回值定義結構如下。
fun test(para1: Int, para2: String): String { ... }複製程式碼
Kotlin中的函式可以是全域性函式,成員函式或者區域性函式,甚至還可以作為某個物件的擴充套件函式臨時新增,這個作為Kotlin的一大實用特性,下文會有具體講解。
Kotlin函式引數還有預設值和可變引數的特性,分別來看一下:
對Kotlin函式中的某個引數可以用“=”號指定其預設值,呼叫函式方法時可不不傳這個引數,但其他引數需要用“=”號指定。下文例子中沒有傳遞引數para2,其實際值為預設值"para2"
fun test(para1: Int, para2: String = "para2", para3: String): String { ... }
test(22, para3 = "hello")複製程式碼
可變引數值的話,需要用關鍵字vararg來定義。這裡需要注意的是,一個函式僅能有一個可變引數。該可變引數不一定得是最後一個引數,但當這種情況下時,呼叫該方法,需要給其他未指明具體值的引數傳值。
fun test(vararg para1: String, para2: String): String { ... }
test("para1", "para4", "para5", para2 = "hello")複製程式碼
2.3 類與繼承
Kotlin中也使用class關鍵字定義類,所有類都繼承於Any類,類似於Java中Object類的概念。類例項化的形式也與Java一樣,但是去掉了new關鍵字。
建構函式
類的建構函式分為primary constructor和secondary constructor,前者只能有一個,而後者可以有多個。如果兩者都未指定,則預設為無引數的primary constructor。
primary constructor是屬於類頭的一部分,用constructor關鍵字定義,無可見性欄位定義時可省略。初始化程式碼需要單獨寫在init程式碼塊中,方法引數只能在init程式碼塊和變數初始化時使用。
secondary constructor也是用constructor關鍵字定義,必須要直接或間接代理primary constructor。
class Student(name: String) { // primary constructor
var mName: String = name
init {
println("Student is called " + name)
}
constructor(age: Int, name: String):this(name) {
println("Student is ${age} years old")
}
}複製程式碼
繼承
類繼承使用符號“:”表示,介面實現也一樣,不做原本Java中的extends和implement關鍵字區分。Kotlin有一點與Java大為不同,即Java中類預設可被繼承,只有被final關鍵字修飾的類才不能被繼承。而Kotlin中直接取消了final關鍵字,所有類均預設不可被繼承。神馬?這還怎麼物件導向程式設計?先別急,Kotlin中新增了open關鍵字,僅有被open修飾的類才可以被繼承。
單例與伴隨物件
日常開發中寫一個單例類是很常見的行為,Kotlin中直接將這種設計模式提升到語言級別,使用關鍵詞object定義單例類。這裡需要注意,是全小寫。Kotlin中區分大小寫,Java中原本指所有類的父類Object已棄用。單例類訪問直接使用類名,無建構函式。
object Shop(name: String) {
fun buySomething() {
println("Bought it")
}
}
Shop.buysomething()複製程式碼
Java中使用static標識一個類裡的靜態屬性或方法,可以被這個類的所以實現使用。Kotlin改為使用伴隨物件,用companion修飾單例類object,來實現靜態屬性或方法功能。
class Mall(name: String) {
companion object Shop {
val SHOP_NAME: String = "McDonald" // 等同於Java中寫public static String
fun buySomething() { // 等同於Java中寫public static void
println("Bought it")
}
}
}
Mall.buySomething()複製程式碼
2.4 邏輯語句
if-else語句
Kotlin中的if-else語句與Java一致,結構上都是if (條件A) { 條件A為真要執行的操作 } else { 條件A為假要執行的操作 }
這裡主要要介紹的是Kotlin的一個特點,即if-else語句可以作為一個邏輯表示式使用。不僅如此,邏輯表示式還可以以程式碼塊的形式出現,程式碼塊最後的表示式作為該塊的值。
// 邏輯表示式的使用
fun maxNum(x: Int, y: Int): Int {
var max = if (x > y) x else y
return max
}
// 程式碼塊形式的邏輯表示式
fun maxNumPlus(x: Int, y: Int): Int {
var max = if (x > y) {
println("Max number is x")
x
} else {
println("Max number is y")
y
}
return max
}複製程式碼
when語句
Kotlin中的when語句取代了Java中的switch-case語句,功能上要強大許多,可以有多種形式的條件表達。與if-else一樣,Kotlin中的when也可以作為邏輯表示式使用。
// 邏輯表示式的使用
fun judge(obj: Any) {
when (obj) {
1 -> println("是數字1")
-1, 0 -> println("是數字0或-1")
in 1..10 -> println("是不大於10的正整數")
"abc" -> println("是字串abc")
is Double -> println("型別是雙精度浮點數")
else -> println("其他操作")
}
}複製程式碼
標籤
Kotlin中可以對任意表示式進行標籤標記,形式為abc@,xyz@。而這些標籤,可以搭配return、break、continue等跳轉行為來使用。
fun labelTest() {
la@ for (i in 1..10) {
println("outer index " + i)
for (j in 1..10) {
println("inner index " + j )
if ( inner % 2 == 0) {
break@la
}
}
}
}複製程式碼
其他
for語句、while語句、continue語句和break語句等邏輯都與Java基本一致,這裡不再贅述。
3 實用特性
3.1 空指標安全
在寫Java程式碼時,最常出現線上上的crash問題大概就是NullPointerException了。技術上來說這樣的問題修復起來很快,沒什麼難度,但往往由於日常開發中沒有寫足夠多的防禦性程式碼,導致此類問題一直困擾著我們。Java作為一個古老的語言並沒有空指標安全功能,這使得當物件層級套用的時候,想要獲取最裡面的某個屬性,需要從外到內依次做一遍非空判斷來避免NPE。相似的場景太多,導致這在程式碼成本上是很大的。
Kotlin中,當我們定義一個變數時,其預設就是非空型別。如果你直接嘗試給他賦值為null,編譯器會直接報錯。Kotlin中將符號“?”定義為安全呼叫操作符。變數型別後面跟?號定義,表明這是一個可空型別。同樣的,在呼叫子屬性和方法時,也可以用字元?進行安全呼叫。Kotlin的編譯器會在寫程式碼時就檢查非空情況,因此下文例子中,當s2有前置條件判斷為非空後,即便其本身是可空型別,也可以安全呼叫子屬性或方法。對於ifelse結構的邏輯,Kotlin還提供了“?:”操作符,極大了簡化了程式碼量又不失可讀性。Kotlin還提供“!!”雙感嘆號操作符來強制呼叫物件的屬性和方法,無視其是否非空。這是一個挺危險的操作符,除非有特殊需求,否則為了遠離NPE,還是少用為妙。
var s1: String = "abc"
s1 = null // 這裡編譯器會報錯
var s2: String? = "abc"
s2 = null // 編譯器不會報錯
var l1 = s1.length // 可正常編譯
var l2 = s2.length // 沒有做非空判斷,編譯器檢查報錯
if (s2 != null) s2.length // Java式的判空方案
s2?.length // Kotlin的安全呼叫操作符?。當s2為null時,s2?.length也為null
if (s2 != null) s2.length else -1 // Java式判空的ifelse邏輯
s2?.length ?: -1 // Kotlin的elvis操作符
s2!!.length // 可能會導致NPE複製程式碼
3.2 擴充套件方法和屬性
相信作為一個Java/Android開發者,大家都寫過很多Base類,繼承原生父類的同時,封裝一些通用方法,供子類使用。亦或是把這類通用方法,專門放置到一個XXUtils類裡,作為工具類出現。這樣做是為了程式碼結構的清晰,但也是一種無奈。由於無法修改原生類的內容,我們只能藉助繼承或者以面向方法的思維來寫工具類。這點在Kotlin裡得到了完美解決。Kotlin支援在包範圍內對已存在的類進行方法和屬性擴充套件。
我們以Android最常用的showToast方法舉個擴充套件方法的例子,以lastIndex屬性舉個擴充套件屬性的例子,如下。在這樣強大的特性下,寫程式碼都成了一種享受。
// 擴充套件方法
fun Context.showLongToast(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
}
// 擴充套件屬性
val <T> ArrayList<T>.lastIndex: Int get() = size -1
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
showLongToast("hello") // 給Context類擴充套件了showToast方法,可以在任何有context的地方直接呼叫了
var mList = ArrayList<String>()
mList.lastIndex // 任何ArrayList均可以呼叫該屬性
...
}
...
}複製程式碼
這裡需要注意兩點:1.擴充套件需要在包級範圍內進行,如果寫在class內是無效的。2.已經存在的方法或屬性,是無法被擴充套件的,依舊會呼叫已有的方法。
3.3 簡潔資料類
相信大家都寫過資料類,或者自動化生成的資料model,通常都是由多個屬性和對應的getter、setter組成。當有大量多屬性的資料類時,不僅這些類會因為大量的getter和setter方法而行數爆炸,也使整個工程方法數驟增。Kotlin中也做了這層特性優化,提供了資料類的簡單實現。不用再寫get和set方法,這些都由編譯器背後去做,你得到的是一個清爽乾淨的資料類。具體使用參考下面的例子。
data class Student (
var name: String,
var age: Int,
var hobby: String?,
var university: String = "NJU"
)
fun printInfo() {
var s: Student = Student("Ricky", 25, "playing Gwent")
println("${s.name} is from ${s.university}, ${s.age} years old, and likes ${s.hobby}")
}複製程式碼
3.4 Anko
Anko是Jetbrains官方提供的一個讓Kotlin開發更快速簡單的類庫,旨在使程式碼書寫更加清晰易懂,形式上為DSL程式設計。
No findViewById
Android開發過程一定都寫過大量的findViewById。這本身就是個消耗資源的方法,編碼時還極為不便,需要強制轉換為具體的View型別才能呼叫其方法。通過引入支援註解的庫,可以使這個過程略微簡單化一些。
// 傳統Android中的View內容初始化
TextView tvName = (TextView) this.findViewById(R.id.tv_name);
tvName.setText("Ricky");
// 註解方式
@BindView(R.id.tv_name)
TextView tvName;
tvName.setText("Ricky");複製程式碼
這樣還是顯得不夠簡潔,而Kotlin給出了一種最為簡便的方式。
import kotlinx.android.synthetic.main.activity_main.* // activity_main為具體的佈局xml檔名
...
tvName.text = "Ricky";複製程式碼
你只需要在具體的頁面中按照上面的格式import下,就可以在整個頁面裡很方便的使用xml裡的view操作了。不需要型別轉換,不需要新建變數,不需要findViewById,孰優孰劣,相信大家心中都有了答案。
Simple startActivity
通常,在Android裡,當我想開啟一個新頁面,並給它傳遞一些引數時,我需要按照如下的方式編碼。
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.putExtra("userid", 10001);
intent.putExtra("username", "ricky");
startActivity(intent);複製程式碼
而強大的Anko給我們提供了一種極為方便的寫法。無論是無參還是有參,還是需要RequestCode,都非常簡潔易懂,是不是一看就特別心動?
startActivity<MainActivity>()
startActivity<MainActivity>("userid" to 10001, "username" to "ricky")
startActivityForResult<MainActivity>(101, "userid" to 10001, "username" to "ricky")複製程式碼
DSL Layout
上面說到不再使用findViewById,還是基於使用xml來編寫Android頁面這個基礎。倘若你想徹底革新寫法,換一種更直觀的DSL方式來寫Android頁面呢?Anko就提供了這樣的方案。相比之下,除了可讀性增加之外,也節約瞭解析xml檔案消耗的資源。
inner class LoginAnkoUI : AnkoComponent<LoginActivity> {
override fun createView(loginAnkoUI: AnkoContext<LoginActivity>): View {
return with(loginAnkoUI) {
verticalLayout {
val textView = textView("使用者名稱") {
textSize = sp(15).toFloat()
textColor = context.resources.getColor(R.color.black)
}.lparams {
margin = dip(10)
height = dip(40)
width username= matchParent
}
val username = editText("輸入...")
button("登入") {
onClick { view ->
toast("Hello, ${username.text}!")
}
}
}
}
}
}複製程式碼
只要最後在Activity里加一句呼叫,便可以使用Anko寫的頁面了。是不是看上去更直觀了呢?
LoginAnkoView().setContentView(this@LoginActivity)複製程式碼
4 快速實踐
4.1 配置Android Studio
作為官方開發語言,在Android Studio 3.0版本中,已經內嵌了對Kotlin的支援。和筆者一樣還在使用2.x版本開發的小夥伴們,也不用擔心需要花時間升級AS才能體驗到Kotlin。JetBrains提供了完善的外掛支援,直接開啟Preferences去配置外掛,找到Kotlin下載安裝下就好啦。
外掛安裝完畢,還需要build.gradle裡新增下依賴。
如果你不清楚當前最新的kotlin版本是什麼的話,這裡也有一個更簡便的方法來給專案新增kotlin依賴。
首先你的專案中要有一份java程式碼,然後在外掛安裝正常的情況下,你可以在Code選單看到一鍵把Java程式碼轉換為Kotlin的功能。
轉換完畢後,當你嘗試修改這個.kt程式碼檔案時,Android Studio便會提醒你Kotlin尚未配置。
這個自動化配置過程,可以看到目前外掛支援到的最新的Kotlin版本。換言之外掛及時最新的話,你這裡就可以選擇到最新的Kotlin版本。這裡也可以選擇只將某個模組配置為支援Kotlin,或者全域性支援。
配置完畢後,我們可以看到build.gradle檔案裡已經自動新增了依賴程式碼,Sync一下就ok了。
由於要充分發揮Kotlin的特性,將Anko的相關程式碼依賴也引入進來
4.2 Demo
下面會給大家展示一個小Demo的核心程式碼,完整程式碼可以檢視KotlinDemo。Demo將分別用Java寫法和Kotlin寫法編寫同樣的頁面,以此對比出優劣。
Demo包含一個Java實現的公共首頁,首頁中有兩個按鈕入口,分別跳轉到用Java編寫的列表頁和用Kotlin編寫的列表頁。各自的列表頁都會實現一個Item點選跳轉到詳情頁的功能,並在詳情頁顯示具體資訊。
Java實現效果:Kotlin實現效果:
列表頁程式碼
// Java實現
public class JListActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {
// View
private ListView listView;
private Button btnClearData;
private Button btnUpdateData;
// Data
private ArrayList<JStudent> studentList = new ArrayList<>();
private JListAdapter listAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_java);
initView();
initData();
}
private void initData() {
listAdapter = new JListAdapter(studentList);
listView.setAdapter(listAdapter);
}
private void initView() {
listView = (ListView) findViewById(R.id.java_list_view);
btnClearData = (Button) findViewById(R.id.java_clear_btn);
btnUpdateData = (Button) findViewById(R.id.java_update_btn);
listView.setDividerHeight(0);
listView.setOnItemClickListener(this);
btnClearData.setOnClickListener(this);
btnUpdateData.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if (view == btnClearData) {
studentList.clear();
listAdapter.notifyDataSetChanged();
showShortToast("已清空");
} else if (view == btnUpdateData) {
studentList.addAll(FakeServer.randomJavaResponse());
listAdapter.notifyDataSetChanged();
showShortToast("已更新10條資料");
}
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(JListActivity.this, JInfoActivity.class);
intent.putExtra("stu_name", studentList.get(i).getName());
intent.putExtra("stu_age", studentList.get(i).getAge());
intent.putExtra("stu_hobby", studentList.get(i).getHobby());
intent.putExtra("stu_university", studentList.get(i).getUniversity());
startActivity(intent);
}
private void showShortToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
}複製程式碼
// Kotlin實現
class KListActivity : AppCompatActivity() {
var studentList: ArrayList<KStudent> = ArrayList()
var listAdapter: KListAdapter = KListAdapter(studentList)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ListUI().setContentView(this@KListActivity)
}
fun clearList() {
studentList.clear()
listAdapter.notifyDataSetChanged()
showShortToast("已清空")
}
fun updateList() {
studentList.addAll(FakeServer.randomKotlinResponse())
listAdapter.notifyDataSetChanged()
showShortToast("已更新10條資料")
}
fun gotoItemInfo(position: Int) {
var student = studentList[position]
startActivity<KInfoActivity>("stu_name" to student.name, "stu_age" to student.age, "stu_hobby" to student.hobby, "stu_university" to student.university)
}
}複製程式碼
資料類程式碼
// Java實現
public class JStudent {
private int id;
private String name;
private int age;
private String hobby;
private String university;
public JStudent(int id, String name, int age, String hobby, String university) {
setId(id);
setName(name);
setAge(age);
setHobby(hobby);
setUniversity(university);
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getHobby() {
return hobby;
}
public String getUniversity() {
return university;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public void setUniversity(String university) {
this.university = university;
}
}複製程式碼
// Kotlin實現
data class KStudent(var id: Int, var name: String, var age: Int, var hobby: String, var university: String)複製程式碼
上面的程式碼對比已經能看出一些驚人的差距,我們再統計一下用兩種方式編寫的具體程式碼行數,以評判兩者的開發效率。
Java Part/LOC | Kotlin Part/LOC | |
---|---|---|
ListActivity | 85 | 38 |
ListUI | 52 | 62 |
InfoActivity | 62 | 29 |
InfoUI | 114 | 120 |
ListAdapter | 71 | 33 |
ListItemUI | 48 | 67 |
Student Data Class | 64 | 1 |
Total | 496 | 350 |
可以看到,使用了Anko編寫的Kotlin頁面UI,在程式碼行數上甚至比xml編寫還要多一點。但是由於不再需要findViewById,對應Activity中減少了很多邏輯,程式碼行也少了很多。同時,這種寫法也節約了CPU去解析xml生成頁面的資源和時間。
最終此Demo中使用Java和Kotlin編寫相同的頁面功能,Kotlin比Java少了30%的程式碼開發量。再加上空指標安全等特性,表現可以說是非常亮眼。
5 結語
Kotlin作為一個JVM上的新語言,充分相容了老大哥Java的諸多功能,又構建了很多自身優秀特性,提供了大量便捷易懂、結構清晰的開發形式。筆者作為一個Android開發,非常樂於在今後的開發中嘗試完全化的Kotlin專案。本文限於篇幅,僅能展現出其諸多特點的一點皮毛,更多新特性還需要各位看官自己在實際使用中挖掘。
套用劉禹錫的一句詩來結束本文吧。“芳林新葉催陳葉,流水前波讓後波”,期待吸收了Java之長的Kotlin,能在未來有更好的表現。