美文网首页
正确理解Kotlin中@JvmOverloads、@JvmSta

正确理解Kotlin中@JvmOverloads、@JvmSta

作者: MiBoy | 来源:发表于2020-03-28 18:47 被阅读0次

    看注解的名字就知道,这是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();
    

    相关文章

      网友评论

          本文标题:正确理解Kotlin中@JvmOverloads、@JvmSta

          本文链接:https://www.haomeiwen.com/subject/vlyoyhtx.html