作為一個有著10多年的軟件開發經驗的工程師在蘇州開發APP做軟體外包蘇州APP開發,我從Android的誕生到逐漸成熟成為主流,學習Java語言的人也越來越多,現如今Kotlin竟成為官方語言。 蘇州智奇勝軟體向來注重技術與效率怎能錯過,我們公司的工程師通常比較宅,只會默默的研究技術,其實我們內部在早就開始關注了Kotlin的語言了,關注了一段時間後分析Kotlin的優勢後決定作為公司的主開發語言,當然不是說我們放棄Java,Java可是我們的強項、主開發語言只是因為Kotlin會更高效。所以我在網上摘錄了一篇帖子與大家一起分享。
相信很多開發人員,尤其是Android開發者都會或多或少聽說過Kotlin,當然如果沒有聽過或者不熟悉也沒有關係。因為本篇文章以及部落格後期的內容會涉及到很多關於Kotlin的知識分享。
在寫這篇文章前的一個多月,Flipboard中國的Android專案確定了正式將Kotlin作為專案開發語言,這就意味著新增的程式碼檔案將以Kotlin程式碼格式出現,而且同時舊的Java程式碼也將會陸陸續續翻譯成Kotlin程式碼。在使用Kotlin的這段時間,被它的簡潔,高效,快捷等等特點震撼,所以有必要寫一篇文章來談一談Kotlin的特性,如若能取得推廣Kotlin的效果則倍感欣慰。 Kotlin的「簡歷」 來自於著名的IDE IntelliJ IDEA(Android Studio基於此開發) 軟件開發公司 JetBrains(位於東歐捷克) 起源來自JetBrains的聖彼得堡團隊,名稱取自聖彼得堡附近的一個小島(Kotlin Island) 一種基於JVM的靜態型別程式語言 來自知名的工具開發商JetBrains,也就決定了Kotlin的基因中必然包含實用與高效等特徵。那我們接下來看一看Kotlin的特點,當然這也是我改用Kotlin的重要原因。
語法簡單,不囉嗦 [css]//variables and constants var currentVersionCode = 1 //變數當前的版本號,型別Int可以根據值推斷出來 var currentVersionName : String = "1.0" //顯式標明型別 val APPNAME = "droidyue.com" //常量APPNAME 型別(String)可以根據值推斷出來
//methods fun main(args: Array<String>) { println(args) }
// class class MainActivity : AppCompatActivity() {
}
// data class 自動生成getter,setting,hashcode和equals等方法 data class Book(var name: String, val price: Float, var author: String)
//支援預設引數值,減少方法過載 fun Context.showToast(message: String, duration:Int = Toast.LENGTH_LONG) { Toast.makeText(this, message, duration).show() }[/css]
Kotlin支援型別推斷,沒有Java那樣的囉嗦。 另外用var表示變數,val表示常量更加的簡潔 方法也很簡單,連function都縮寫成了fun,平添了幾分雙關之意。 類的繼承和實現很簡單,使用:即可 Kotlin每個句子都不需要加分號(;) 空指標安全 空指標(NullPointerException或NPE)是我們使用Java開發程式中最常見的崩潰了。因為在Java中我們不得不寫很多防禦性的程式碼,比如這樣
[css]public void test(String string) { if (string != null) { char[] chars = string.toCharArray(); if (chars.length > 10) { System.out.println(((Character)chars[10]).hashCode()); } } }[/css]
在Kotlin中空指標異常得到了很好的解決。
在型別上的處理,即在型別後面加上?,即表示這個變數或引數以及返回值可以為null,否則不允許為變數引數賦值為null或者返回null 對於一個可能是null的變數或者引數,在呼叫物件方法或者屬性之前,需要加上?,否則編譯無法通過。 如下面的程式碼就是Kotlin實現空指標安全的一個例子,而且相對Java實現而言,簡直是一行程式碼搞定的。
[css]fun testNullSafeOperator(string: String?) { System.out.println(string?.toCharArray()?.getOrNull(10)?.hashCode()) }
testNullSafeOperator(null) testNullSafeOperator("12345678901") testNullSafeOperator("123")
//result null 49 null[/css]
關於空指標安全的原理,可以參考這篇文章研究學習Kotlin的一些方法
支援方法擴充套件 很多時候,Framework提供給我們的API往往都時比較原子的,呼叫時需要我們進行組合處理,因為就會產生了一些Util類,一個簡單的例子,我們想要更快捷的展示Toast資訊,在Java中我們可以這樣做。
[css]public static void longToast(Context context, String message) { Toast.makeText(context, message, Toast.LENGTH_LONG).show(); }
但是Kotlin的實現卻讓人驚奇,我們只需要重寫擴充套件方法就可以了,比如這個longToast方法擴充套件到所有的Context物件中,如果不去追根溯源,可能無法區分是Framework提供的還是自行擴充套件的。
fun Context.longToast(message: String) { Toast.makeText(this, message, Toast.LENGTH_LONG).show() } applicationContext.longToast("hello world")[/css]
注意:Kotlin的方法擴充套件並不是真正修改了對應的類檔案,而是在編譯器和IDE方面做得處理。使我們看起來像是擴充套件了方法。
Lambda, 高階函式,Streams API, 函數語言程式設計支援 所謂的Lambda表示式是匿名函式,這使得我們的程式碼會更加的簡單。比如下面的程式碼就是lambda的應用。
[css]findViewById(R.id.content).setOnClickListener { Log.d("MainActivity", "$it was clicked") }[/css]
所謂的高階函式就是
可以接受函式作為引數 也可以返回函式作為結果 舉一個接受函式作為引數的例子。在Android開發中,我們經常使用SharedPreference來儲存資料,如果忘記呼叫apply或者commit則資料修改不能應用。利用Kotlin中的高階函式的功能,我們能更好的解決這個問題
[css]fun SharedPreferences.editor(f: (SharedPreferences.Editor) -> Unit) { val editor = edit() f(editor) editor.apply() }
//實際呼叫 PreferenceManager.getDefaultSharedPreferences(this).editor { it.putBoolean("installed", true) }[/css]
當然這上面的例子中我們也同時使用了方法擴充套件這個特性。
Kotlin支援了Streams API和方法引用,這樣函數語言程式設計更加方便。比如下面的程式碼就是我們結合Jsoup,來抓取某個proxy網站的資料,程式碼更加簡單,實現起來也快速。
[css]fun parse(url: String): Unit { Jsoup.parse(URL(url), PARSE_URL_TIMEOUT).getElementsByClass("table table-sm") .first().children() .filter { "tbody".equals(it.tagName().toLowerCase()) } .flatMap(Element::children).forEach { trElement -> ProxyItem().apply { trElement.children().forEachIndexed { index, element -> when (index) { 0 -> { host = element.text().split(":")[0] port = element.text().split(":")[1].toInt() } 1 -> protocol = element.text() 5 -> country = element.text() } } }.let(::println) } }[/css]
字串模板 無論是Java還是Android開發,我們都會用到字串拼接,比如進行日誌輸出等等。在Kotlin中,字串模板是支援的,我們可以很輕鬆的完成一個字串陣列的組成
[css]val book = Book("Thinking In Java", 59.0f, "Unknown") val extraValue = "extra" Log.d("MainActivity", "book.name = ${book.name}; book.price=${book.price};extraValue=$extraValue")[/css]
注意:關於字串拼接可以參考這篇文章Java細節:字串的拼接
與Java互動性好 Kotlin和Java都屬於基於JVM的程式語言。Kotlin和Java的互動性很好,可以說是無縫連線。這表現在
Kotlin可以自由的引用Java的程式碼,反之亦然。 Kotlin可以現有的全部的Java框架和庫 Java檔案可以很輕鬆的藉助IntelliJ的外掛轉成kotlin Kotlin應用廣泛 Kotlin對Android應用開發支援廣泛,諸多工具,比如kotterknife(ButterKnife Kotlin版),RxKotlin,Anko等等,當然還有已經存在的很多Java的庫都是可以使用的。
除此之外,Kotlin也可以編譯成Javascript。最近使用Kotlin寫了一段抓取proxy的程式碼,實現起來非常快捷。甚至比純JavaScript實現起來要快很多。
[css]fun handle(): Unit { window.onload = { document.getElementsByClassName("table table-sm").asList().first() .children.asList().filter { "TBODY".equals(it.tagName.toUpperCase()) } .flatMap { it.children.asList() }.forEach { var proxyItem = ProxyItem() it.children.asList().forEachIndexed { index, element -> when (index) { 0 -> { proxyItem.host = element.trimedTextContent()?.split(":")?.get(0) ?: "" proxyItem.port = element.trimedTextContent()?.split(":")?.get(1)?.trim()?.toInt() ?: -1 } 1 -> proxyItem.protocol = element.trimedTextContent() ?: "" 5 -> proxyItem.country = element.trimedTextContent() ?: "" } }.run { console.info("proxyItem $proxyItem") }
} } }[/css]
關於效能 Kotlin的執行效率和Java程式碼的執行效率理論上一致的。有時候Kotlin可能會顯得高一些,比如Kotlin提供了方法的inline設定,可以設定某些高頻方法進行inline操作,減少了執行時的進棧出棧和儲存狀態的開銷。
讀到這裏,是不是想要嘗試一下Kotlin呢,它簡潔的語法,彙集諸多特性,高效率實現等等,已經在國外風生水起,國外的Pintereset, Square, Flipboard等公司已經開始應用到生產中。
關於轉向Kotlin 其實,我在做決定之前(當時Kotlin還沒有被欽定)也曾有過考慮,是不是選擇了Kotlin就意味著放棄Java呢,冷靜下來想一想,其實並不是那麼回事,因為Kotlin與Java語法太相近,以及在Kotlin中無時無刻不在和Java相關的東西打交道,所以這點顧慮不是問題的。
對於個人的專案來轉向Kotlin,通常不是很難的選擇,畢竟Kotlin是那麼優秀的語言,相信很多人還是願意嘗試並使用這個事半功倍的語言的。
而比較難抉擇的情況是如果如何讓團隊轉用Kotlin,個人認為團隊難以轉用的原因有很多,比如學習成本,歷史包袱等等。但其實根本原因還是思維方式的問題,歪果仁喜歡用工具來提升開發效率,因為人力成本很高。而國內團隊提高效率的辦法通常是增加成員。好在Flipboard 美國團隊自2015年(可能更早)就引入了Kotlin,因此中國團隊這邊選用Kotlin也更加順水推舟。當然更主要的是目前團隊規模不大,成員一致認可Kotlin的優點。
關於團隊轉用Kotlin的方法,一般比較行得通的辦法是自上而下的推行。這就意味著要麼直接的技術負責人比較開明要麼就是需要有人來不斷推介來影響團隊。
做個比較現實的比擬,Java就像是一趟從我的家鄉保定開往北京西的耗時將近2個小時甚至更長的普通列車,而Kotlin則是那趟僅需40分鐘就能到達的高鐵。通常的人都會選擇高鐵,因為它節省了時間和提高了體驗。這個時間和體驗對應程式設計中的,我想應該是高效率和高可讀性,可維護性的程式碼。
現在好了,有了Google的支援,Kotlin轉Android相信在不久的將來就會全面展開。篡改Python的一句名言「人生苦短,我用Kotlin」,這樣一個高效實用的語言應該會被越來越多的團隊所接受,並應用到開發生產中。當然也希望在國內環境下大放異彩。
智奇勝軟體的iOS程式支援Objective-C和Swift語言開發。
By:Taiyangchen