看注解的名字就知道,这是kotlin 为了让Java更好的使用kotlin 编码而写的注解。
一 、@JvmOverloads
一句话就是为了解决Java不能重载kotlin 有默认参数的方法
看代码
Kotlin中代码
fun test(a: String, b: Int = 0, c: String="abc"){
xxx
}
在Java中能调用的方法
void test(String a,int b,String c){
xxx
}
这样就有个问题是:默认参数没起到作用
但是如果使用的了@JvmOverloads注解:
@JvmOverloads fun test(a: String, b: Int=0, c:String="abc"){
}
相当于在Java中声明了3个方法:
void test(String a)
void test(String a, int b)
void test(String a, int b, String c)
是不是很方便,再也不用写那么多重载方法了。
注:该注解也可用在构造方法和静态方法。
class MyLayout: LinearLayout {
@JvmOverloads
constructor(context:Context, attributeSet: AttributeSet? = null, defStyleAttr: Int = 0): super(context, attributeSet, defStyleAttr)
}
相当Java中的:
public class MyLayout extends LinearLayout {
public MyLayout(Context context) {
this(context, null);
}
public MyLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
二、@JvmStatic、@JvmField
一句话就是为了解决在Java中不能直接调用kotlin 中的静态方法和静态变量
看代码:
Java代码中有静态方法和静态属性
public class TestStatic {
private int num = 0;
public static final String S = "a";
public static void test() {
System.out.println("call method");
}
}
转换成kotlin 代码
class TestStatic {
private val num = 0
companion object {
val S = "a"
fun test() {
println("call method")
}
}
}
静态方法和静态变量会变成伴生对象里面的方法和伴生对象的属性,那么在调用的时候是这样的:
public static void main(String[] args) {
TestStatic.Companion.test();
String s = TestStatic.Companion.getS();
}
如果要使转换后的 Kotlin 代码在 Java 上调用起来和以前的习惯一样,则需要分别使用 @JvmStatic 和 @JvmField 注解,才能使它们暴露为静态方法或静态字段,如下:
class TestStatic {
private val num = 0
companion object {
@JvmField
val S = "a"
@JvmStatic
fun test() {
println("call method")
}
}
}
这样 Java 对 Kotlin 的调用习惯就和以前一样了:
public static void main(String[] args) {
TestStatic.test();
String s = TestStatic.S;
}
伴生函数:
在 “companion object” 中的公共函数必须用使用 @JvmStatic 注解才能暴露为静态方法。
如果没有这个注解,这些函数仅可用作静态 Companion 字段上的实例方法。
伴生常量:
在 companion object 中的公共、非 const 的属性 实际上为常量 必须用 @JvmField 注解才能暴露为静态字段。
如果没有这个注解,这些属性只能作为静态 Companion 字段中奇怪命名的 ‘getters’ 实例。而只使用 @JvmStatic 而不是 @JvmField 的话,会将奇怪命名的 ‘getters’ 移到类的静态方法中,但仍然是不正确的。
三、@JvmName
一句话就是对要调用的类的名字和方法的名字进行重命名。
比如你用IDE 创建一个kotlin file,并命名为PersonFile.kt, 而你在Java中引用这个文件的时候 只能 用PersonFile.xxx ,如果把这个注解作用在文件上:
@file:JvmName("Person")
那么你就可以用 Person.xxx 去调用
那么还可以作用在方法上 ,重命名这个方法
四、@JvmMultifileClass
如果多个文件中生成了相同的 Java 类名(包名相同并且类名相同或者有相同的 @JvmName 注解)通常是错误的。然而,编译器能够生成一个单一的 Java 外观类,它具有指定的名称且包含来自所有文件中具有该名称的所有声明。 要启用生成这样的外观,请在所有相关文件中使用 @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();
网友评论