Преобразование статических переменных из Java в Kotlin

Я пытаюсь преобразовать следующий код в Kotlin И еще есть один из классов (Foo), используемых Java. Каков правильный способ сделать это преобразование?

Оригинальная 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 – Котлин

 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 или VALUES (ошибка: «частный доступ»)

если я поставил «const» перед C_ID, он работает … но я не могу сделать то же самое с VALUES («const» может ТОЛЬКО использоваться на примитивах или String)

Есть ли другой способ, которым я должен это делать (так как код Java и код Kotlin могут получить доступ ко всему в Foo)?

Текущая семантика исходит от кандидата Котлина Бета :

@JvmField и объекты

Мы сделали стратегию создания чистых полей (в отличие от пар get / set ) более предсказуемыми: теперь только свойства, аннотированные как @JvmField , lateinit или const отображаются как поля для Java-клиентов. Старые версии использовали эвристику и создали статические поля в объектах безоговорочно, что противоречит нашей первоначальной цели дизайна по умолчанию для API, совместимых с двоичной совместимостью.

Кроме того, экземпляры singleton теперь доступны под именем INSTANCE (вместо INSTANCE$ ).

В соответствии с этим и ссылкой , существует три способа работы со свойствами object Kotlin из Java:

  • Используйте Foo.INSTANCE .

    По умолчанию свойства object не будут статическими полями для Java, но Java может получить доступ к свойствам через экземпляр объекта FooFoo.INSTANCE .

    Таким образом, выражение будет Foo.INSTANCE.getC_ID() .

  • Отметьте свойство с помощью @JvmStatic аннотации:

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

    Это будет генерировать статический getter для C_ID вместо экземпляра экземпляра Foo который будет доступен как Foo.getC_ID() .

  • Используйте аннотацию @JvmField для объявления свойства:

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

    Это заставит компилятор Kotlin генерировать статическое поле для Java вместо свойства. Затем в Java вы можете получить к нему доступ как статическое поле: Foo.C_ID .

    Но он не будет работать на свойствах без полей поддержки, подобных all в вашем примере.

Для примитивов, как вы сказали, можно использовать const который будет иметь тот же эффект, что и @JvmField с точки зрения видимости в Java.

Кстати, когда дело доходит до методов, ситуация такая же, и для них есть @JvmStatic аннотация.

В вашем классе 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) } } } 

Затем вы можете вызвать Foo.getAll () и Foo.C_ID, Foo.C_NAME и Foo.VALUES.

Вы должны иметь доступ к значениям «путь 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) } fun main(args: Array<String>) { Foo.all.forEach { it->println(it) } } 

В результате:

 ID NAME Process finished with exit code 0