Kotlin-40.kotlin調用Java之二(Call Java from Kotlin)

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

繼續上一章

5.Java空安全和平臺類型(Null-Safety and Platform Type)

在Java中任何引用都可能是null,這使Kotlin要求Java對象嚴格空安全是不現實的!
Java聲明的類型在Kotlin中會被特別對待,稱爲平臺類型(platform types)!
kotlin對平臺類型的空檢查(Null-checks)會放寬,因此它們在kotlin中的安全性與在Java中一樣!
示例:
    val list = ArrayList<String>() // 非空(構造函數結果)
    list.add("Item")
    val size = list.size() // 非空(原生 int)
    val item = list[0] // 推斷爲平臺類型(普通Java對象)

當調用平臺類型的方法時,Kotlin不會在編譯時檢查可空性null錯誤, 
但在運行時調用可能報錯,出現空指針異常NullPointerException或者Kotlin斷言阻止null傳播!
    item.substring(1) // 允許,如果item == null,可能會拋出異常

平臺類型(platform types)是不可標示(non-denotable),意味着不能在kotlin語言中明確地寫下指定!
當把平臺類型值賦值給Kotlin變量時,可以依賴類型推斷,或者選擇期望的類型(可空null或非空null類型均可):
    val nullable: String? = item // 允許可空(null)
    val notNull: String = item // 允許非空(notNull),運行時可能失敗(null)

如果選擇非空類型(kotlin),編譯器在賦值時會觸發斷言assertion,防止Kotlin的非空變量保存空值(null)!
當把平臺值傳遞給期待非空的Kotlin函數時,也會觸發斷言!
總而言之,編譯器盡力阻止空值(null)通過程序傳播(鑑於泛型原因,有時不能完全消除)

1.平臺類型表示法(Notation for Platform Type)
    如上所述,平臺類型不能在程序中顯式表示,因此在kotlin語言中沒有相應語法! 
    但是有時編譯器或IDE要在錯誤/參數信息中顯示平臺類型,所以可用助記符標記:
        T!                       表示T 或者 T?
        (Mutable)Collection<T>!  表示T的Java集合 可變或不可變, 可空或不可空
        Array<(out) T>!          表示T(或T子類)的Java數組 可空或者不可空

2.可空性註解(Nullability annotation)
    具有可空性註解的Java類型並不表示爲平臺類型,而表示爲實際可空或非空的Kotlin類型,
    編譯器支持多種可空性註解:
        JetBrains (@Nullable and @NotNull from the org.jetbrains.annotations package)
        Android (com.android.annotations and android.support.annotations)
        JSR-305 (javax.annotation)
        FindBugs (edu.umd.cs.findbugs.annotations)
        Eclipse (org.eclipse.jdt.annotation)
        Lombok (lombok.NonNull).

6.Java類型映射(Mapped type)

Kotlin會特殊處理部分的Java類型,映射到相應的Kotlin類型,映射只發生在編譯期間,運行時表示保持不變!

1.Java基本類型映射到相應Kotlin類型:
    Java類型      Kotlin類型
    byte         kotlin.Byte
    short        kotlin.Short
    int          kotlin.Int
    long         kotlin.Long
    char         kotlin.Char
    float        kotlin.Float
    double       kotlin.Double
    boolean      kotlin.Boolean

2.Java包裝類(基本類型)映射成可空Kotlin類:
      Java類型                  Kotlin類型
    java.lang.Byte             kotlin.Byte?
    java.lang.Short            kotlin.Short?
    java.lang.Integer          kotlin.Int?
    java.lang.Long             kotlin.Long?
    java.lang.Character        kotlin.Char?
    java.lang.Float            kotlin.Float?
    java.lang.Double           kotlin.Double?
    java.lang.Boolean          kotlin.Boolean?
注意: 當java包裝類作爲類型參數,會被映射成平臺類型,例如,List<java.lang.Integer>在Kotlin中會變成List<kotlin.Int!>

3.Java一些非基本類型也會映射:
      Java類型                  Kotlin類型
    java.lang.Object           kotlin.Any!
    java.lang.Cloneable        kotlin.Cloneable!
    java.lang.Comparable       kotlin.Comparable!
    java.lang.Enum             kotlin.Enum!
    java.lang.Annotation       kotlin.Annotation!
    java.lang.Deprecated       kotlin.Deprecated!
    java.lang.CharSequence     kotlin.CharSequence!
    java.lang.String           kotlin.String!
    java.lang.Number           kotlin.Number!
    java.lang.Throwable        kotlin.Throwable!

4.Java集合類型在Kotlin中既能只讀,也能可變,因此有以下映射(Kotlin集合在kotlin.collections包)    
    Java類型          Kotlin只讀類型     Kotlin可變類型               平臺類型(platform type)
    Iterator<T>       Iterator<T>       MutableIterator<T>           (Mutable)Iterator<T>!
    Iterable<T>       Iterable<T>       MutableIterable<T>           (Mutable)Iterable<T>!
    Collection<T>     Collection<T>     MutableCollection<T>         (Mutable)Collection<T>!
    Set<T>            Set<T>            MutableSet<T>                (Mutable)Set<T>!
    List<T>           List<T>           MutableList<T>               (Mutable)List<T>!
    ListIterator<T>   ListIterator<T>   MutableListIterator<T>       (Mutable)ListIterator<T>!
    Map<K, V>         Map<K, V>         MutableMap<K, V>             (Mutable)Map<K, V>!
    Map.Entry<K, V>   Map.Entry<K, V>   MutableMap.MutableEntry<K,V> (Mutable)Map.(Mutable)Entry<K, V>!

5.Java數組在Kotlin中映射:
    Java類型    Kotlin類型
    int[]       kotlin.IntArray!
    String[]    kotlin.Array<(out) String>!

7.在Kotlin中的Java泛型(Java generics in Kotlin)

Kotlin泛型與Java有些不同,當在Kotlin中使用Java泛型時,會執行一些轉換:
    1.Java通配符(wildcard)轉換成類型投影(type projection)
        Foo<? extends Bar> 轉換成 Foo<out Bar!>!
        Foo<? super Bar> 轉換成 Foo<in Bar!>!

    2.Java原始類型轉換成星投影(star projection)
        List 轉換成 List<*>! 即List<out Any?>!

和Java一樣,Kotlin在運行時不保留泛型,即對象不會把類型參數傳遞到構造器!
即不能區分ArrayList<Integer>()和ArrayList<Character>() 
這使得is操作符不能檢測泛型,Kotlin只允許is檢測星投影的泛型類型:
    if (a is List<Int>) // 錯誤: 無法檢查a是否爲Int列表       
    if (a is List<*>) // OK: 不保證列表內容

簡書:http://www.jianshu.com/p/bc65be16a489
CSDN博客: http://blog.csdn.net/qq_32115439/article/details/75093931
GitHub博客:http://lioil.win/2017/07/13/Kotlin-javaInKotlin2.html
Coding博客:http://c.lioil.win/2017/07/13/Kotlin-javaInKotlin2.html

發佈了156 篇原創文章 · 獲贊 38 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章