kotlin 与java 互操作
简介
大多数情况下,你不需要关注这个问题。但是,如果你的代码中包含了部分Java代码,了解这些可能帮你解决一些棘手的问题,同时让你设计的Api更加可靠
互操作性与可空性
Java世界里所有对象都可能是null,当一个kotlin函数返回string类型值,你不能想当然地认为它的返回值就能符合kotlin关于空值的规定
kotlin
fun main() {
val my = MyClass()
val value = my.getCanNullValue()
println(value?.capitalize())
}
java
public class MyClass {
public String value;
public String getCanNullValue(){
return value;
}
}
类型映射
代码运行时,所有的映射类型都会重新映射回对应的java类型
fun main() {
val my = MyClass()
my.value = "a123"
val value = my.getCanNullValue()
println(value.javaClass)
}
结果为:class java.lang.String
属性访问
不需要调用相关setter方法,你可以使用赋值语法来设置一个java字段值了
val my = MyClass()
my.value = "a123"
@JvmName
这个注解可以改变字节码中生成的类名或方法名称,如果作用在顶级作用域(文件中),则会改变生成对应Java类的名称。如果作用在方法上,则会改变生成对应Java方法的名称。
kotlin
@file:JvmName("FooKt")
@JvmName("foo1")
fun foo() {
println("Hello, Jvm...")
}
java
// 相当于下面的Java代码
public final class FooKt {
public static final void foo1() {
String var0 = "Hello, Jvm...";
System.out.println(var0);
}
}
第一个注解@file:JvmName("FooKt")
的作用是使生成的类名变为FooKt
,第二个注解的作用是使生成的方法名称变为foo1
。
@JvmField
Kotlin编译器默认会将类中声明的成员变量编译成私有变量,Java语言要访问该变量必须通过其生成的getter方法。而使用上面的注解可以向Java暴露该变量,即使其访问变为公开(修饰符变为public)。
Kotlin
class JavaToKotlin {
@JvmField
val info = "Hello"
}
@JvmOverloads
由于Kotlin语言支持方法参数默认值,而实现类似功能Java需要使用方法重载来实现,这个注解就是为解决这个问题而生的,添加这个注解会自动生成重载方法
Kotlin
@JvmOverloads
fun prinltInfo(name: String, age: Int = 1) {
println("$name $age")
}
java
public static void main(String[] args) {
MyKotlin.prinltInfo("arrom");
MyKotlin.prinltInfo("arrom", 20);
}
@JvmStatic
@JvmStatic注解的作用类似于@JvmField,可以直接调用伴生对象里的函数
class JavaToKotlin {
@JvmField
val info = "Hello"
companion object {
@JvmField
val max: Int = 200
@JvmStatic
fun loadConfig(): String {
return "loading config"
}
}
}
@Throws
由于Kotlin语言不支持CE(Checked Exception),所谓CE,即方法可能抛出的异常是已知的。Java语言通过throws
关键字在方法上声明CE。为了兼容这种写法,Kotlin语言新增了@Throws
注解,该注解的接收一个可变参数,参数类型是多个异常的KClass实例。Kotlin编译器通过读取注解参数,在生成的字节码中自动添加CE声明。
Kotlin
@Throws(IllegalArgumentException::class)
fun div(x: Int, y: Int): Float {
return x.toFloat() / y
}
Java
// 生成的代码相当于下面这段Java代码
public static final float div(int x, int y) throws IllegalArgumentException {
return (float)x / (float)y;
}
添加了@Throws(IllegalArgumentException::class)
注解后,在生成的方法签名上自动添加了可能抛出的异常声明(throws IllegalArgumentException),即CE。
@Synchronized
用于产生同步方法。Kotlin语言不支持synchronized
关键字,处理类似Java语言的并发问题,Kotlin语言建议使用同步方法进行处理
Kotlin
@Synchronized
fun start() {
println("Start do something...")
}
java
// 生成的代码相当于下面这段Java代码
public static final synchronized void start() {
String var0 = "Start do something...";
System.out.println(var0);
}
函数类型操作
Java中没有函数类型,所以,在Java里,kotlin函数类型使用FunctionN这样的名字的接口来表示,N代表入参的个数,一共有24个这样的接口,从Function0到Function23,每个接口都包含一个invoke函数,调用匿名函数需要调用invoke
kotlin:
val funcp:(String) -> String = {
it.capitalize()
}
java:
Function1 funcp = ArromKt.getFuncp();
funcp.invoke("arrom");
作者:Arrom
链接:https://juejin.cn/post/7039268896083279902
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。