Kotlin-45.Java調(diào)用kotlin之三(Call Kotlin from Java)

官方文檔: http://kotlinlang.org/docs/reference/java-to-kotlin-interop.html

8.@JvmName解決java方法簽名相同(Handling signature clashes)

最突出的例子是由于類型擦除(type erasure)引發(fā):
    // 類型擦除: 無法區(qū)分List<String>和List<Int>
    fun List<String>.filterValid(): List<String>
    fun List<Int>.filterValid(): List<Int>
    這兩個函數(shù)在java中不能同時定義,因為它們的JVM簽名相同: filterValid(Ljava/util/List;)Ljava/util/List

在Kotlin中用相同名稱,需要用@JvmName標注其中的一個(或兩個),并指定不同名稱:
    fun List<String>.filterValid(): List<String>

    @JvmName("filterValidInt")
    fun List<Int>.filterValid(): List<Int>

    在Kotlin中,可以用相同名稱filterValid()訪問;
    在Java中,需要分別用filterValid()和filterValidInt()訪問

同樣注解@JvmName也適用于屬性x和函數(shù)getX():
    val x: Int
        @JvmName("getX_prop")
        get() = 15

    fun getX() = 10

    在Java中,需要分別用getX_prop()和getX()訪問

9.Java方法重載(Overloads Generation)

如果Kotlin函數(shù)的參數(shù)有默認值并且使用@JvmOverloads注解,
那么在Java中多個重載方法, 示例如下:
    @JvmOverloads fun f(a: String, b: Int = 0, c: String = "abc") {
    }

    // kotlin函數(shù)的每一個有默認值的參數(shù),都會重載生成一個額外java方法:    
    void f(String a, int b, String c) {            
    }
    void f(String a, int b) {            
    }
    void f(String a) {            
    }

該注解也適用于構(gòu)造函數(shù)和靜態(tài)方法, 但不能用于抽象方法(包括接口的方法)

對于次構(gòu)造函數(shù)(Secondary Constructors), 如果所有參數(shù)都有默認值,
那么會生成一個公有public的無參構(gòu)造函數(shù)(沒有@JvmOverloads注解也會生效)!

10.受檢異常(Checked Exception)

從前幾章《kotlin-33.異常(Exception)》可知,Kotlin沒有受檢異常!
所以Kotlin函數(shù)簽名不會聲明拋出異常(throws Exception),例如:    
    // kotlin (example.kt), 拋出異常
    package demo
    fun foo() {
        throw IOException()
    }

    // kotlin編譯生成的Java方法
    public void foo() { // 錯誤: foo()沒有聲明throws IOException
        throw IOException()
    }

因為由kotlin函數(shù)生成的Java方法foo()沒有聲明throws IOException, 所以Java編譯器報錯!
為了解決這個問題,需要在Kotlin中使用@Throws注解(相當于在Java中聲明throws IOException)
    // kotlin
    @Throws(IOException::class)
    fun foo() {
        throw IOException()
    }

    // kotlin編譯生成的Java方法
    public void foo() throws IOException {
        throw IOException()
    }

11.型變泛型(Variant generics)

當Kotlin類使用聲明處型變(declaration-site variance)時,在Java中有兩種用法!
示例:
    // kotlin
    class Box<out T>(val value: T)
    interface Base
    class Derived : Base

    fun boxDerived(value: Derived): Box<Derived>{            
    }
    fun unboxBase(box: Box<Base>): Base {            
    }
    unboxBase(boxDerived("s")) // 正確: 在Java中Box<Base>泛型是不型變的!

    // 將上述kotlin函數(shù)轉(zhuǎn)換成Java方法       
    Box<Derived> boxDerived(Derived value) {            
    }
    Base unboxBase(Box<Base> box) {            
    }
    unboxBase(boxDerived("s")) // 錯誤: 因為在Java中Box<Base>泛型是不型變的!

    //使用Java通配符類型<? extends Base>模擬kotlin聲明處型變
    Base unboxBase(Box<? extends Base> box) {            
    }
    unboxBase(boxDerived("s")) // 正確

此外, 對于協(xié)變定義的Box(在kotlin中Box<in T>), 在java中使用Box<? extends Super>
注意:當參數(shù)類型是final時,通配符? extends沒有意義,
        例如在Box<String>中的String類是final,沒有子類(不能被繼承extends)

如果在默認沒有通配符處要求java泛型通配符, 可以使用@JvmWildcard注解:
    // kotlin函數(shù)
    fun boxDerived(value: Derived): Box<@JvmWildcard Derived> {            
    }

    // 轉(zhuǎn)換成java方法 
    Box<? extends Derived> boxDerived(Derived value) {        
    }

相反,如果不需要泛型通配符,可以使用@JvmSuppressWildcards注解;
@JvmSuppressWildcards不僅可用于單個類型參數(shù),還可用于整個聲明(如函數(shù)或類),從而抑制其中的所有通配符!
    // kotlin函數(shù)
    fun unboxBase(box: Box<@JvmSuppressWildcards Base>): Base {            
    }

    // 轉(zhuǎn)換成java方法 
    Base unboxBase(Box<Base> box) {            
    }

12.Nothing類型翻譯(Translation of type Nothing)

類型Nothing是Kotlin特有的,在Java中沒有對應類型!
每個Java引用類型(包括java.lang.Void)都接受null, 但是kotlin的Nothing不行!
Nothing類型不能在Java世界中準確表示,所以Nothing類型在java中會消失(原始類型raw type):
    // kotlin的Nothing類型
    fun emptyList(): List<Nothing> = listOf()
    
    // 翻譯成轉(zhuǎn)換成java方法, List<Nothing>變成原始類型List, Nothing類型消失了
    List emptyList() {            
    }

簡書:http://www.itdecent.cn/p/acdd8ba0830b
CSDN博客: http://blog.csdn.net/qq_32115439/article/details/75452680
GitHub博客:http://lioil.win/2017/07/19/Kotlin-kotlinInJava3.html
Coding博客:http://c.lioil.win/2017/07/19/Kotlin-kotlinInJava3.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容