将静态变量从Java转换为Kotlin

Jef*_*ell 25 static field properties kotlin

我正在尝试将以下代码转换为Kotlin,并且仍然使用Java使用的一个类(Foo).进行此转换的正确方法是什么?

原始Java:

public class Foo {
   public static final String C_ID = "ID";
   public static final String C_NAME = "NAME";
   public static final String[] VALUES = {"X", "Y", "Z"};

   public static String[] getAll() {
       return new String[] {C_ID, C_NAME};
   }
}

public class Bar {
    public void doStuff() {
        String var1 = Foo.C_ID;
        String[] array1 = Foo.VALUES;
        String[] array2 = Foo.getAll();
    }
}
Run Code Online (Sandbox Code Playgroud)

自动转换Foo到Kotlin

object Foo {
    val C_ID = "ID"
    val C_NAME = "NAME"
    val VALUES = arrayOf("X", "Y", "Z")

    val all: Array<String>
        get() = arrayOf(C_ID, C_NAME)
}
Run Code Online (Sandbox Code Playgroud)

问题:

Bar类无法再访问C_ID或VALUES(错误:"私有访问")

如果我把"常量",在C_ID面前,它的工作原理......但我不能做同样的VALUES("常量",只能在primatives或字符串使用)

我应该采用不同的方式(因此Java代码和Kotlin代码都可以访问Foo中的所有内容)吗?

hot*_*key 35

目前的语义来自Kotlin Beta Candidate:

@JvmField和对象

我们已经取得了战略产生纯净的领域(而不是get/ set对)更可预测:仅标注为性能从现在开始@JvmField,lateinitconst暴露的字段Java客户端.较旧的版本使用启发式方法并无条件地在对象中创建静态字段,这违反了我们的默认初始设计目标,即具有二进制兼容性友好的API.

此外,现在可以通过名称INSTANCE(而不是INSTANCE$)访问单例实例.

根据这个和参考,有三种方法来处理object来自Java 的Kotlin的属性:

  • 使用Foo.INSTANCE.

    默认情况下,属性object不是Java的静态字段,但Java可以通过Foo对象实例访问属性- Foo.INSTANCE.

    所以表达式将是Foo.INSTANCE.getC_ID().

  • 使用@JvmStatic注释标记属性:

    object Foo {
        @JvmStatic val C_ID = "ID"
        //...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这将生成静态getter,C_ID而不是Foo实例getter,可以访问Foo.getC_ID().

  • @JvmField在属性声明上使用注释:

    object Foo {
        @JvmField val C_ID = "ID"
        //...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这将使Kotlin编译器为Java而不是属性生成静态字段.然后在Java中,您可以将其作为静态字段访问:Foo.C_ID.

    但是如果没有像all示例中那样支持字段,它将不适用于属性.

对于原语,正如您所说,可以使用const哪些原语与@JvmFieldJava中的可见性具有相同的效果.

顺便说一下,当谈到方法时,情况是一样的,并且有@JvmStatic注释.


Fel*_*shi 7

在你的foo类中,你可以将这些属性和方法放在一个伴侣对象中:

class Foo {

  companion object {
     val C_ID:String = "ID"
     val C_NAME:String = "NAME"
     @JvmField val VALUES = arrayOf("X", "Y", "Z")

     fun getAll():Array<String> {
        return arrayOf(C_ID, C_NAME)
     }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以调用Foo.getAll()和Foo.C_ID,Foo.C_NAME和Foo.VALUES.