正确理解Kotlin中@JvmOverloads、@JvmStatic、@JvmName、@JvmField注解@JvmMultifileClass

看注解的名字就知道,这是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();
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容