- Kotlin注解之JvmName
我们首先定义给 Int定义一个扩展函数。
fun Int.compare(num: Int): Int {
return if (this > num) {
this
} else num
}
在Kotlin代码中我们可以直接调用:
println(2.compare(1))
但是在 Java代码中我们的调用方式变为:
public static void main(String[] args) {
int num = TestAnotionKt.compare(2, 1);
System.out.println(num);
}
其实通过观察Kotlin转换为Java的代码就可以比较容易理解Java中的调用方式了,可以发现扩展被转换成了一个静态方法。类名变为:Koltin文件名+Kt
public final class TestAnotionKt {
public static final int compare(int $this$compare, int num) {
return $this$compare > num ? $this$compare : num;
}
}
其实上述的方法类似于一个工具类:这个时候我们就可以使用JvmName注解来给Java的调用方式重新取一个名字。
@file:JvmName("IntUtils")
package com.example.annotation
fun Int.compare(num: Int): Int {
return if (this > num) {
this
} else num
}
则在Java中可以进行如下调用:
int num = IntUtils.compare(1, 2);
System.out.println(num);
通过将Kotlin代码转换成 Java代码,可以看出JvmName注解的作用:可以修改静态方法所在的类名。
public final class IntUtils {
public static final int compare(int $this$compare, int num) {
return $this$compare > num ? $this$compare : num;
}
}
- Kotlin注解之 JvmMultifileClass
JvmMultifileClass的作用是可以将多个个kt文件里面的代码合并到一个Javaclass文件中。
文件TestAnotionFunA.kt
@file:JvmName("CommonUtils")
@file:JvmMultifileClass
package com.example.annotation
fun functionA() {
}
文件TestAnotionFunB.kt
@file:JvmName("CommonUtils")
@file:JvmMultifileClass
package com.example.annotation
fun functionB() {
}
TestAnotionFunA.kt转换成Java
final class CommonUtils__TestAnotionFunAKt {
public static final void functionA() {
}
}
public final class CommonUtils {
public static final void functionA() {
CommonUtils__TestAnotionFunAKt.functionA();
}
}
TestAnotionFunB.kt转换成Java
final class CommonUtils__TestAnotionFunBKt {
public static final void functionB() {
}
}
public final class CommonUtils {
public static final void functionB() {
CommonUtils__TestAnotionFunBKt.functionB();
}
}
java中调用
CommonUtils.functionA();
CommonUtils.functionB();
如果不使用JvmMultifileClass,编译会报错。
Duplicate JVM class name 'com/example/annotation/CommonUtils' generated from: package-fragment com.example.annotation, package-fragment com.example.annotation
- Kotlin注解之JvmField
我们首先定义一个Koltin的Person类
class Person(var name: String, var age: Int)
转换成Java如下:
public final class Person {
@NotNull
private String name;
private int age;
@NotNull
public final String getName() {
return this.name;
}
public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name = var1;
}
public final int getAge() {
return this.age;
}
public final void setAge(int var1) {
this.age = var1;
}
public Person(@NotNull String name, int age) {
Intrinsics.checkParameterIsNotNull(name, "name");
super();
this.name = name;
this.age = age;
}
}
在Java中使用这个Person类:
Person p1 = new Person("haha", 18);
p1.setName("XiXi");
p1.setAge(16);
而在Kotlin中可以直接使用:
val person = Person("haha", 18)
person.name = "xixi"
person.age = 16
如果希望在Java中 的使用方式与在Kotlin中相同,应该如何处理呢?
在Kotlin代码中加上@JvmField
class Person(@JvmField var name: String, var age: Int)
转换成对应的Java文件为:
public final class Person {
@JvmField
@NotNull
public String name;
private int age;
public final int getAge() {
return this.age;
}
public final void setAge(int var1) {
this.age = var1;
}
public Person(@NotNull String name, int age) {
Intrinsics.checkParameterIsNotNull(name, "name");
super();
this.name = name;
this.age = age;
}
}
在Java文件中就可以以相同的方式调用:
Person p1 = new Person("haha", 18);
p1.name = "xixi";
- Kotlin 注解之JvmStatic
public final class TestJvmStatic {
public static final int a = 1;
private static final int b = 2;
private static int c = 3;
@JvmField
public static int d = 4;
@JvmField
public static final int e = 5;
public static final TestJvmStatic.Companion Companion = new TestJvmStatic.Companion((DefaultConstructorMarker)null);
@JvmStatic
public static final void doOperateA() {
Companion.doOperateA();
}
public static final class Companion {
public final int getB() {
return TestJvmStatic.b;
}
public final int getC() {
return TestJvmStatic.c;
}
public final void setC(int var1) {
TestJvmStatic.c = var1;
}
@JvmStatic
public final void doOperateA() {
}
public final void doOperateB() {
}
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
在Java文件中调用:
TestJvmStatic.doOperateA();
TestJvmStatic.Companion.doOperateB();
int a = TestJvmStatic.a;
int e = TestJvmStatic.e;
int d = TestJvmStatic.d;
TestJvmStatic.Companion.getB();
TestJvmStatic.Companion.getC();
通过对比可以发现:@JvmStatic 和 @JvmField 注解,才能使方法或者字段暴露为静态方法或静态字段,这样Java调用方式和正常的Java静态方法的调用方式一样了。
- Koltin注解之JvmSynthetic
如果想一个函数给kotlin代码调用 而不给java的代码调用 ,函数上面加上这个注解即可。
@file:JvmName("IntUtils")
package com.example.annotation
@JvmSynthetic
fun Int.compare(num: Int): Int {
return if (this > num) {
this
} else num
}
fun main() {
print(2.compare(3))
}
转换成Java 代码如下:
@JvmName(
name = "IntUtils"
)
public final class IntUtils {
// $FF: synthetic method
public static final int compare(int $this$compare, int num) {
return $this$compare > num ? $this$compare : num;
}
}
可以发现:加上@JvmSynthetic注解后,该方法只能在Kotlin中调用了,在Java中会找不到这个方法 。