Kotlin 基础12 - Kotlin 与 Java 互操作
@JvmName
Kotlin 顶层函数在 Java 里都被当作静态方法看待和调用。
可以使用 @JvmName
注解指定编译类的名字。加到文件的最上方。
@file:JvmName("Hero")
@JvmOverloads
设计一个可能会暴露给 Java 用户使用的 API 时,最好使用 @JvmOverloads
注解。
这样无论是 Kotlin 开发者还是 Java 开发者,都会对这个 API 的可靠性感到满意。
// Hero.kt
@file:JvmName("Hero")
@JvmOverloads
fun handOverFood(leftHand: String = "berries", rightHand: String = "beef") {
println("Mmmm... you hand over some delicious $leftHand and $rightHand.")
}
// Java
Hero.handOverFood();
Hero.handOverFood("pizza");
Hero.handOverFood("pizza", "beer");
@JvmField
可以给 Kotlin 属性添加 @JvmField
注解,暴露它的支持字段给 Java 调用者,从而避免使用 getter 方法。
// Kotlin
class Spellbook {
@JvmField
val spells = listOf("Magic Ms. L", "Lay on Hans")
}
// Java
Spellbook spellbook = new Spellbook();
for (String spell : spellbook.spells) {
System.out.println(spell);
}
@JvmField
注解还能用来以静态方式提供伴生对象里定义的值。
// Kotlin
class Spellbook {
...
companion object {
val MAX_SPELL_COUNT = 10
}
}
// Java
Spellbook.Companion.getMAX_SPELL_COUNT();
// Kotlin
class Spellbook {
...
companion object {
@JvmField
val MAX_SPELL_COUNT = 10
}
}
// Java
System.out.println(Spellbook.MAX_SPELL_COUNT);
@JvmStatic
@JvmStatic
注解的作用类似于 @JvmField
,允许直接调用伴生对象里的函数。
// Kotlin
class Spellbook {
@JvmField
val spells = listOf("Magic Ms. L", "Lay on Hans")
companion object {
@JvmField
val MAX_SPELL_COUNT = 10
@JvmStatic
fun getSpellbookGreeting() = println("I am the Great Grimoire!")
}
}
// Java
Spellbook.getSpellbookGreeting();
@Throws
Kotlin 中所有的异常都是未检查异常。对于是否要用 try/catch 语句包裹可能会导致异常的代码,Kotlin 编译器不做强制要求。
使用 @Throws
注解,Kotlin 中函数要抛出的异常就能让调用者知道。
注解给 Java 版本的函数添加了一个 throws 关键字。
@Throws(IOException::class)
fun acceptApology() {
throw IOException()
}
Java 中的函数类型
Java 8 之前的 JDK 版本并不支持 lambda 表达式。
在 Java 里,Kotlin 函数类型是用 FunctionN 这样的名字的接口来表示的,FunctionN 中的 N 代表值参数目。
val translator = { utterance: String ->
println(utterance.toLowerCase().capitalize())
}
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
...
Function1<String, Unit> translator = Hero.getTranslator();
translator.invoke("TRUCE");