I'm trying to convert the following code to Kotlin AND still have one of the classes (Foo) used by Java. What is the proper way of making this conversion?

Original 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();
    }
}

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)
}

问题:

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

if I put "const" in front of C_ID, it works... but I cannot do the same with VALUES ("const" can ONLY be used on primatives or String)

Is there a different way I should be doing this (so both Java code and Kotlin code can access everything in Foo)?

推荐答案

The current semantics come from Kotlin Beta Candidate:

@JvmField and objects

We have made the strategy for generating pure fields (as opposed to get/set pairs) more predictable: from now on only properties annotated as @JvmField, lateinit or const are exposed as fields to Java clients. Older versions used heuristics and created static fields in objects unconditionally, which is against our initial design goal of having binary-compatibility-friendly APIs by default.

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

根据这一点和reference,有三种方法可以处理来自Java的Kotlin object的属性:

  • Use Foo.INSTANCE.

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

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

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

    object Foo {
        @JvmStatic val C_ID = "ID"
        //...
    }
    

    这将生成C_ID%的静电获取程序,而不是可以作为Foo.getC_ID()访问的Foo实例获取程序.

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

    object Foo {
        @JvmField val C_ID = "ID"
        //...
    }
    

    This will make Kotlin compiler generate a static field for Java instead of property. Then in Java you can access it as a static field: Foo.C_ID.

    但是,如果没有支持字段(如示例中的all),它将无法在属性上工作.

如您所述,对于原语,可以使用const,这在Java中的可见性方面与@JvmField具有相同的效果.

顺便说一句,说到方法,情况是一样的,它们有@JvmStatic个注释.

Kotlin相关问答推荐

在Kotlin中,有没有一种函数方法将一个列表(N个元素)映射到一个相邻元素之和列表(N—1个元素)?

如何避免使用公共类实现内部接口

在Jetpack Compose中创建波浪式文本动画:顺序中断问题

用Quarkus和Reactor重写异步过滤器中的数据流

同时也是一个字符串的 Kotlin 枚举

kotlin 父类具有依赖于抽象变量的变量

如何从 kotlin 中的数据类访问 val?

Jetpack BottomNavigation - java.lang.IllegalStateException:Already attached to lifecycleOwner

AIDL 中的 Parcelize 注释:Incompatible types: Object cannot be converted to MyCustomObject

Android 导航组件 - 向上导航打开相同的片段

使用 Hilt 注入 CoroutineWorker

Kotlin:什么是 kotlin.String!类型

Kotlin-通过与属性列表进行比较来筛选对象列表

如何在Kotlin中创建填充空值的通用数组?

Android 上的 Kotlin:将map到list

在Kotlin中为Android编写库会有开销吗?

用于代码生成的ANTLR工具版本4.7.1与当前运行时版本4.5.3不匹配

不推荐使用仅限生命周期的LifecycleEvent

Failure delivering result on activity result

如何修复未解析的参考生命周期范围?