原作者:在這周的文章中,他要消除你對在應用程式中使用Kotlin的所有恐懼。他講解了Java和Kotlin之間的互通性,即你的應用程式代碼可以一部分由Java完成,而另一部分由Kotlin中完成。這樣你就可以逐步開始使用Kotlin,且越來越有信心。 ...
時間:Jul, 4, 2017
原文鏈接:https://antonioleiva.com/kotlin-from-java/
Kotlin最神奇特性之一是它能與Java完全集成。這就是說儘管你的應用程式的所有代碼都是用Java編寫的,而你仍然可以在Kotlin中創建一個類,從Java中使用它,且不會出現任何問題。
這有兩個好處:
-
你可以在Java項目中使用Kotlin:在任何已經啟動的項目中,你可以現在開始用Kotlin編寫新的代碼。然後從Java代碼中調用它。
- 如果你對Kotlin還心有餘悸,可以在Java中做這個部分:很多人問我在Android上的某些情況下,Kotlin是否有不足。理論上,所有事情都能夠勝任,但實際上,還無法知道(目前,還沒有人用Kotlin在Android上完成“所有事情”)。事實是,這無關緊要,如果有些操作不能在Kotlin中完成,還可以回Java中去實現它。
今天我們將看看這種相容性是如何工作的,以及怎樣從Java使用Kotlin代碼。
軟體包級別的函數
在Kotlin中,函數不需要在類中,但Java不是的。那麼我們如何調用函數呢?試想一下,我們有一個文件utils.kt,如下所示:
1 fun logD(message: String) { 2 Log.d("", message) 3 } 4 5 fun logE(message: String) { 6 Log.e("", message) 7 }
在Java中,我們可以通過UtilsKt類來訪問它們,並使用一些靜態方法:
1 UtilsKt.logD("Debug"); 2 UtilsKt.logE("Error");
在之前的文章,你已經看到我喜歡擴展函數。而在Java中,它們如何做?如我們有以下:
1 fun ViewGroup.inflate(resId: Int, attachToRoot: Boolean = false): View { 2 return LayoutInflater.from(context).inflate(resId, this, attachToRoot) 3 }
註意:
雖然它們可能在某個時候出現,但我還沒有明確地對此進行講解。函數的自變數可能有預設值。這就是說,如果我們不特別指明,它們就使用在聲明時指定的值。如我們要在Java中使用,這就阻止我們使用方法重載。
該函數用於ViewGroup
。它收到一個佈局,併在其父視圖使其膨脹。
如果我們要在Java中使用它,會得到什麼?
1 View v = UtilsKt.inflate(parent, R.layout.view_item, false);
如你所見,應用此函數的對象(接收方)是作為參數添加到函數中。另外,由於在Java中我們不能使用預設值,可選擇參數是強制性的。
如果要在Java中生成相應的重載,你可以為該函數使用@JvmOverloads註釋。這樣,你不需要在Java中指定false:
1 @JvmOverloads 2 fun ViewGroup.inflate(resId: Int, attachToRoot: Boolean = false): View { 3 return LayoutInflater.from(context).inflate(resId, this, attachToRoot) 4 }
1 View v = UtilsKt.inflate(parent, R.layout.view_item);
如果你希望在Java中使用時指定類名稱,則可以使用註釋來修改它。在文件utils.kt中,添加在package之前:
1 @file:JvmName("AndroidUtils")
現在Java中的類將被命名:
1 AndroidUtils.logD("Debug"); 2 AndroidUtils.logE("Error"); 3 View v = AndroidUtils.inflate(parent, R.layout.view_item, false);
實例和靜態欄位
在Java中,我們使用欄位來存儲狀態。它們可以是實例欄位,這意味著每個對象都有自己的,或靜態的(所有類的實例都將共用它們)。
如果我們嘗試在Kotlin中找到對應的,那麼它將是屬性和伴隨對象。如果我們有這樣一個類:
1 class App : Application() { 2 3 val appHelper = AppHelper() 4 5 companion object { 6 lateinit var instance: App 7 } 8 9 override fun onCreate() { 10 super.onCreate() 11 instance = this 12 } 13 14 }
這在Java中是如何工作?您可以簡單地訪問作為靜態欄位的伴隨對象,以及使用getter和setter的屬性:
1 AppHelper helper = App.instance.getAppHelper();
你會編譯沒有問題。作為val,它只生成Java中的getter。如果是var,我們也會有一個setter。
因為它使用了lateinit註釋,訪問instance已經自動工作,它會自動公開Kotlin用於存儲狀態的欄位。但是假設我們創建一個常數:
1 companion object { 2 lateinit var instance: App 3 val CONSTANT = 27 4 }
你會看到你不能直接訪問它。你必須通過Companion內部類訪問:
1 KotlinTest.Companion.getCONSTANT()
誰更好?要在Java中以同樣的方式暴露出一個靜態欄位的方式,你需要一個新的註釋:
1 @JvmField val CONSTANT = 27
現在可以使用Java代碼:
1 int c = App.CONSTANT;
如果你在伴隨對象中有函數,則可以使用@JvmStatic註釋將其轉換為靜態方法。
結論
你看到了由Java使用Kotlin代碼非常簡單。在這裡我已經展示了一些最典型的事例,其他都可以以非常相似的方式實現。
我希望如果你有任何疑問,這能夠說服你開始在項目中使用Kotlin。如果你要認真思考,我建議你閱讀這組Kotlin文章,你可以在這裡瞭解更多關於Kotlin的信息。