在上一篇博客中,介紹了kotlin調(diào)用java代碼,這篇文章介紹java調(diào)用kotlin代碼。
屬性
kotlin屬性被編譯成如下java元素:
- 一個(gè)getter方法,方法名為屬性名加上get前綴。
- 一個(gè)setter方法,方法名為屬性名加上set前綴(只針對var修飾的變量屬性有效)
- 一個(gè)私有域,名字和屬性名相同
例如,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調(diào)用名為isOpen(),setter調(diào)用名為setOpen()。這條規(guī)則適用于任何認(rèn)為類型的屬性,而不僅僅是Boolean類型。
包級別的函數(shù)
所有的聲明在org.foo.bar包中example.kt文件的函數(shù)和屬性,都會被編譯成名為org.foo.bar.ExampleKt的Java類的靜態(tài)方法。
//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();
當(dāng)存在許多生成同一個(gè)java類名的文件時(shí),通常是個(gè)錯(cuò)誤。然而,編譯器有能力生成一個(gè)單獨(dú)的java類包含所有要生成這個(gè)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();
靜態(tài)方法
上文中提到過,kotlin將包級別的函數(shù)展示為靜態(tài)方法。Kotlin同樣可以將命名對象或伴生對象的方法生成靜態(tài)方法,如果你用@JvmStatic注解標(biāo)注這些方法。如果你使用這個(gè)注解,編譯器會同時(shí)在封閉類中生成一個(gè)靜態(tài)方法,也在對象本身生成一個(gè)靜態(tài)方法。例如:
class C{
? ? companion object{
? ? ? ? ?@JvmStatic fun foo(){}
? ? ? ? ?fun bar(){}
}
}
現(xiàn)在,foo()是java中的靜態(tài)方法,但是bar()不是。
重載函數(shù)
正常情況下,如果你的kotlin方法含有默認(rèn)參數(shù)值,在java中只會看到其全部簽名,包含所有的參數(shù)。如果你希望暴露多個(gè)重載給java調(diào)用者,可以使用@JvmOverloads注解。
@JvmOverloads fun f(a:String,b:Int=0,c:String="abc"){
}
對于每個(gè)帶有默認(rèn)值的參數(shù),這回生成一個(gè)額外的重載方法,這個(gè)方法會移除包含有這個(gè)參數(shù)的這個(gè)參數(shù)右邊所有參數(shù)列表。在這個(gè)例子中,會生成如下的方法:
//Java
void f(String a,int b,String c){}
void f(String a,int b){}
void f(String a){}
這個(gè)注解對于構(gòu)造方法和靜態(tài)方法同樣有效,但是不能適用于抽象方法,包括接口聲明的方法。
受檢異常
如上文所述,kotlin沒有受檢異常。因此,java簽名的kotlin方法不拋出異常,如果我們有如下的方法:
//example.kt
fun foo(){
? ? ? ?throw IOException()
}
我們想在java調(diào)用這個(gè)方法并且捕獲異常:
//Java
try{
demo.Example.foo();
}catch(IOException e){ //產(chǎn)生錯(cuò)誤:foo()沒有在拋出列表中聲明IOException
? ? //..
}
為了解決這個(gè)問題,在kotlin中使用@Throws注解:
@Throws(IOException::class)
fun foo(){
throw IOException()
}