jvm signature 属性_在Java中嵌入Cotlin实现动态生成程序

定义在命名对象的属性或者 companion对象属性是静态的.

这些私有字段可以通过下面方式暴露给java:

@JvmField 标注;

lateinit 修饰词;

const 修饰词

属性标注 @JvmField 使得它的静态字段和本身有相同可见性.

class Key(val value: Int) {

companion object {

@JvmField

val COMPARATOR: Comparator<Key> = compareBy<Key> { it.value }

}

}

// JavaKey.COMPARATOR.compare(key1,key2);// public static final field in Key class延迟初始化late-initialized属性或者 companion 对象和setter方法有相同可见性.

object Singleton {

lateinit var provider: Provider

}

// JavaSingleton.provider=newProvider();// public static non-final field in Singleton class属性带有const(in classes as well as at the top level) 被转换成静态:

// file example.kt

object Obj {

const val CONST = 1

}

class C {

companion object {

const val VERSION = 9

}

}

const val MAX = 239

In Java:

int c = Obj.CONST;

int d = ExampleKt.MAX;

int v = C.VERSION;

静态方法

Kotlin 将包级的函数解释为静态方法. Kotlin

也可以为命名对象和或者协作对象生成静态方法 ,只要加上 @JvmStatic. 如果使用这个标注,

编译器将生成类和对象自己的相同方法:

class C {

companion object {

@JvmStatic fun foo() {}

fun bar() {}

}

}

Now, foo() is static in Java,

while bar() is not:

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

命名对象:

object Obj {

@JvmStatic fun foo() {}

fun bar() {}

}

In Java:

Obj.foo(); // works fine

Obj.bar(); // error

Obj.INSTANCE.bar(); // works, a call through the singleton instance

Obj.INSTANCE.foo(); // works too

@JvmStatic annotation can also be

applied on a property of an object or a companion object making its

getter and setter methods be static members in that object or the

class containing the companion object.

可见性

Kotlin

可见性映射到java有如下规则:

private 编译为private 成员;

private top-level 定义便以为 package-local

定义;

protected 保留 protected (注意protected可以在java相同包内访问,Kotlin

不能, 因此 ;

internal 定义变成 public 。 internal 类通过名称改写(name mangling),

使得在java中很难发生冲突,允许子类使用同名重载;

public 保留 public.

KClass

有时候你需要调用

Kotlin方法,使用 KClass参数. 没有自动从 Class 到 KClass的办法,因此不得不手动代码 Class.kotlin 扩展属性:

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

Handling signature clashes with @JvmName

有时 Kotlin中函数命名, 在 JVM 需要使用另外的名字。

最可能发生在类型重名 type erasure:

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

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

这两函数不能被同时定义, 因为他们的 JVM

前面一样: filterValid(LLjava/util/List;. 如果想要在 Kotlin中使用, 需要其中一个

(或两个) 使用 @JvmName指定不同名字:

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

@JvmName("filterValidInt")

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

在Kotlin可以使用同名filterValid, 在Java

中分别使用 filterValid 和 filterValidInt.

相同的情形是,当我们需要属性和方法重名时, x 和 getX():

val x: Int

@JvmName("getX_prop")

get() = 15

fun getX() = 10

默认值重载

通常, 如果写一个 Kotlin 函数带有默认值, 在 Java

中仅仅生成一个完整的方法, 带有所有参数. 如果想要导出多个方法,

可以使用 @JvmOverloads 标注.

该标注也可用于构造器, 静态方法等等. 可用于抽象方法,

包括接口上的方法.

class Foo @JvmOverloads constructor(x: Int, y: Double = 0.0) {

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

...

}

}

// Constructors:

Foo(int x, double y)

Foo(int x)

// Methods

void f(String a, int b, String c) { }

void f(String a, int b) { }

void f(String a) { }

注意, 如果类构造参数全部带有缺省值,

即使没有 @JvmOverloads 也会生成一个无参构造器.

异常检查

Kotlin 没有异常检查. 因此, 通常,

Kotlin到Java没有异常抛出:

// 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

// ...

}

出现 Java 编译错误,

因为 foo() 没有定义 IOException. 要解决这个问题,

使用@Throws 标注:

@Throws(IOException::class)

fun foo() {

throw IOException()

}

Null-安全

从Java调用 Kotlin 函数,

没办法阻止传入参数为 null . Kotlin 生成运行时检查所有 public 函数传递参数为非空. 这种办法使得Java代码中立刻得到NullPointerException .

Variant generics

When Kotlin classes make use

of declaration-site

variance, 在 Java 代码中有两使用选项. 看看下面的类,以及两个方法:

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) { ... }

问题是 Kotlin

可以调用 unboxBase(boxDerived("s")), 但Java不允许, 因为在 Java

中类 Box 决定于参数 T,

因此 Box 不是 Box.的子类。

要使得代码在java中执行,需要如下定义:

Base unboxBase(Box

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值