kotlin彙總10-Java調用kotlin

Java可以很容易的調用kotlin代碼

1屬性

比如kotlin有var firstName: String
其實等同於在Java中下面的定義

private String firstName;

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

2.Package-Level函數

kotlin代碼

// example.kt
package demo

class Foo

fun bar() {
}

在Java調用如下

// Java
new demo.Foo();
demo.ExampleKt.bar();

可以通過@file:JvmName註釋告訴Java,比如

//kotlin代碼
@file:JvmName("DemoUtils")

package demo

class Foo

fun bar() {
}

//Java調用

// Java
new demo.Foo();
demo.DemoUtils.bar();

如果在同一自動生成的類(包名和類名一致)囊括了多個kotlin文件則需要使用@file:JvmMultifileClass,比如

// oldutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass

package demo

fun foo() {
}
// newutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass

package demo

fun bar() {
}

在Java中調用

// Java
demo.Utils.foo();
demo.Utils.bar();

3.對象實例的字段(fields)

可以通過@JvmField修飾,比如

//kotlin
class C(id: String) {
    @JvmField val ID = id
}
// Java
class JavaClient {
    public String getID(C c) {
        return c.ID;
    }
}

4.靜態字段

4.1 使用@JvmField修飾

//kotlin
class Key(val value: Int) {
    companion object {
        @JvmField
        val COMPARATOR: Comparator<Key> = compareBy<Key> { it.value }
    }
}
// Java
Key.COMPARATOR.compare(key1, key2);
// public static final field in Key class

4.2使用lateinit修飾

//kotlin
object Singleton {
    lateinit var provider: Provider
}
// Java
Singleton.provider = new Provider();
// public static non-final field in Singleton class

4.3使用const修飾

//kotlin
// file example.kt

object Obj {
    const val CONST = 1
}

class C {
    companion object {
        const val VERSION = 9
    }
}

const val MAX = 239
//java
int c = Obj.CONST;
int d = ExampleKt.MAX;
int v = C.VERSION;

5.靜態方法

通過@JvmStatic修飾

//kotlin
class C {
    companion object {
        @JvmStatic fun foo() {}
        fun bar() {}
    }
}
//java
C.foo(); // works fine
C.bar(); // error: not a static method
C.Companion.foo(); // instance method remains
C.Companion.bar(); // the only way it works
//kotlin
object Obj {
    @JvmStatic fun foo() {}
    fun bar() {}
}

//java
Obj.foo(); // works fine
Obj.bar(); // error
Obj.INSTANCE.bar(); // works, a call through the singleton instance
Obj.INSTANCE.foo(); // works too

6.可見域

  • kotlin的private成員函數變成java的private成員函數
  • kotlin的private頂級聲明(直接在kotlin文件下面)變成java的包可見聲明
  • kotlin的protected在Java還是一樣,但是需要注意的是Java的protected可以訪問同一個包下面的所有,但是kotlin是private+子類可見,所以明顯Java的protected可見域比kotlin要大
  • kotlin的internal變成java的public
  • kotlin的public變成Java的public

7.KClass

有些時候需要從KClass類型中獲取Kotlin方法,但是Class不等於KClass,所以你需要如下

kotlin.jvm.JvmClassMappingKt.getKotlinClass(MainView.class)

8.使用@JvmName處理簽名衝突

比如下面

fun List<String>.filterValid(): List<String>
fun List<Int>.filterValid(): List<Int>

上面兩個在Jvm的簽名都是一樣的:filterValid(Ljava/util/List;)Ljava/util/List;
所以需要區分,使用@JvmName

fun List<String>.filterValid(): List<String>

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

//在Java中調用
filterValid
filterValidInt

一個同樣的例子

val x: Int
    @JvmName("getX_prop")
    get() = 15

fun getX() = 10

9.生成覆載方法

比如,有kotlin代碼

fun f(a: String, b: Int = 0, c: String = "abc") {
    ...
}
//調用
f(a)
f(a, b)
f(a, b, c)

要想在Java也這樣調用,所以對方法加上@JvmOverloads

@JvmOverloads fun f(a: String, b: Int = 0, c: String = "abc") {
    ...
}

// Java,自動生成的
void f(String a, int b, String c) { }
void f(String a, int b) { }
void f(String a) { }

10.檢查異常

比如有kotlin代碼

// example.kt
package demo

fun foo() {
    throw IOException()
}

//我們希望在java如下調用
// Java
try {
  demo.Example.foo();
}
catch (IOException e) { // error: foo() does not declare IOException in the throws list
  // ...
}

需要如下添加@Throws註釋,如下

@Throws(IOException::class)
fun foo() {
    throw IOException()
}

11.Null安全

不保證

12.變體泛型

如下kotlin代碼

class Box<out T>(val value: T)

interface Base
class Derived : Base

fun boxDerived(value: Derived): Box<Derived> = Box(value)
fun unboxBase(box: Box<Base>): Base = box.value

//可以天真的用下面的Java代碼代替
Box<Derived> boxDerived(Derived value) { ... }
Base unboxBase(Box<Base> box) { ... }

//但是有個問題,
unboxBase(boxDerived("s")) 這行代碼可以在kotlin沒問題,因爲Box<Derived>是Box<Base>的子類型(注意out修飾了泛型),但是在Java,我們知道肯定報錯的。所以
Base unboxBase(Box<Base> box) { ... }//ERROR,要改成如下
Base unboxBase(Box<? extends Base> box) { ... } //這樣就可以使用unboxBase(boxDerived("s"))

13.Nothing的轉化

//kotlin
fun emptyList(): List<Nothing> = listOf()
// is translated to Java
List emptyList() { ... }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章