Как скрыть поле поддержки Kotlin lateinit var с Java?

В Котлине, предположим, у меня есть класс:

class MyKotlinClass {
    lateinit var field: String
}

Согласно документам:

Свойства с поздней инициализацией также отображаются как поля. Видимость поля будет такой же, как видимость установщика свойства lateinit.

Я могу использовать в коде java либо myKotlinClass.field, либо myKotlinClass.getField(). Я хочу отключить доступ к полю и оставить доступ только через getter и setter.

Как я могу этого добиться и остаться модификатором lateinit?


person Michael Spitsin    schedule 15.03.2017    source источник


Ответы (3)


Вы можете использовать @JvmSynthetic, скрывает объявления из Java (а не из Kotlin). Просто добавьте аннотацию в поле поддержки свойства:

@field:JvmSynthetic
lateinit var field: String

Хотя поле останется public в байт-коде, оно также будет иметь модификатор synthetic, который не позволяет использовать его в исходных кодах Java. Однако поле, кажется, все еще доступно через отражение во время выполнения.

См. Также: еще один вопрос о @JvmSynthetic (хотя однозначного ответа нет. там).

person hotkey    schedule 15.03.2017
comment
Спасибо. Это именно то, что мне нужно. - person Michael Spitsin; 15.03.2017
comment
Я проверил сгенерированный байт-код с помощью Kotlin 1.0.6, и поле поддержки все еще было общедоступным - person voddan; 15.03.2017
comment
@voddan, но теперь у него должен быть модификатор synthetic, не так ли? С этим модификатором его использование в исходных кодах Java должно стать недействительным. - person hotkey; 15.03.2017
comment
@voddan, вот так: public synthetic Ljava/lang/String; s. Или вы нашли способ ссылаться на поле из Java? - person hotkey; 15.03.2017
comment
@hotkey, в поле отображается ACC_SYNTHETIC. Позвольте мне проверить, могу ли я получить к нему доступ с Java - person voddan; 15.03.2017
comment
@hotkey, вы были абсолютно правы, извините за -1. Пожалуйста, отредактируйте свой A (добавьте где-нибудь пробел :), чтобы я мог проголосовать за него - person voddan; 15.03.2017
comment
@voddan, без проблем, обновил ответ с более подробной информацией о том, что это делает. :) - person hotkey; 15.03.2017
comment
Есть ли способ скрыть сгенерированные геттер и сеттер, не устанавливая их как частные? - person stefana; 09.03.2018

Классическим решением этой проблемы было бы использование делегирования свойств. :

import kotlin.properties.Delegates

class MyKotlinClass {
    var field: String by Delegates.notNull()
}

Этот код делает именно то, что вы просили в вопросе

person voddan    schedule 15.03.2017
comment
Спасибо за альтернативные решения. Я также проверил это обсуждение обсудить.kotlinlang.org/t/notnull -delegate-vs-lateinit / 1923 - чтобы увидеть фактическую разницу между lateinit и Delegates.notNull() - person Michael Spitsin; 16.03.2017

Видимость поля lateinit определяется видимостью установщика соответствующего свойства, поэтому другой вариант - иметь свойство с непубличным установщиком:

lateinit var field: String
    private set

Недостатком этого подхода является то, что сам сеттер становится недоступным вне класса.

person Ilya    schedule 15.03.2017