java中调用kotlin代码
在上一篇博客中,介绍了kotlin调用java代码,这篇文章介绍java调用kotlin代码。
属性
kotlin属性被编译成如下java元素:
- 一个getter方法,方法名为属性名加上get前缀。
- 一个setter方法,方法名为属性名加上set前缀(只针对var修饰的变量属性有效)
- 一个私有域,名字和属性名相同
例如,var firstName:String被编译成如下java声明:
private String firstName;
public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName){
this.firstName=firstName;
}
如果属性名字以'is'起始,那么我们采用另一种命名映射方式:getter方法的名字和属性名字一样,setter方法的名字会将属性中的is替换为set。例如,对于isOpen属性,getter调用名为isOpen(),setter调用名为setOpen()。这条规则适用于任何认为类型的属性,而不仅仅是Boolean类型。
包级别的函数
所有的声明在org.foo.bar包中example.kt文件的函数和属性,都会被编译成名为org.foo.bar.ExampleKt的Java类的静态方法。
//example.kt
package demo
class Foo
fun bar(){
}
//Java
new demo.Foo();
demo.ExampleKt.bar();
生成的java类的名字可以用@JvmName注解来指定:
@file:JvmName("DemoUtils")
package demo
class Foo
fun bar(){
}
//Java
new demo.Foo();
demo.DemoUtils.bar();
当存在许多生成同一个java类名的文件时,通常是个错误。然而,编译器有能力生成一个单独的java类包含所有要生成这个Java类的kotlin文件中声明的属性。通过在所有此类文件中使用@JvmMultifileClass注解来允许这种集成。
//oldutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass
package demo
fun foo(){
}
//newutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass
package demo
fun bar(){
}
//Java
demo.Utils.foo();
demo.Utils.bar();
静态方法
上文中提到过,kotlin将包级别的函数展示为静态方法。Kotlin同样可以将命名对象或伴生对象的方法生成静态方法,如果你用@JvmStatic注解标注这些方法。如果你使用这个注解,编译器会同时在封闭类中生成一个静态方法,也在对象本身生成一个静态方法。例如:
class C{
companion object{
@JvmStatic fun foo(){}
fun bar(){}
}
}
现在,foo()是java中的静态方法,但是bar()不是。
重载函数
正常情况下,如果你的kotlin方法含有默认参数值,在java中只会看到其全部签名,包含所有的参数。如果你希望暴露多个重载给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){}
这个注解对于构造方法和静态方法同样有效,但是不能适用于抽象方法,包括接口声明的方法。
受检异常
如上文所述,kotlin没有受检异常。因此,java签名的kotlin方法不抛出异常,如果我们有如下的方法:
//example.kt
fun foo(){
throw IOException()
}
我们想在java调用这个方法并且捕获异常:
//Java
try{
demo.Example.foo();
}catch(IOException e){ //产生错误:foo()没有在抛出列表中声明IOException
//..
}
为了解决这个问题,在kotlin中使用@Throws注解:
@Throws(IOException::class)
fun foo(){
throw IOException()
}