Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to hide Kotlin's lateinit var backing field from Java?

In Kotlin, suppose, I have class:

class MyKotlinClass {
    lateinit var field: String
}

According to docs:

Late-Initialized properties are also exposed as fields. The visibility of the field will be the same as the visibility of lateinit property setter.

I can use in java code either myKotlinClass.field or myKotlinClass.getField(). I want to disable field access and remain only access through getter and setter.

How can I achieve this and remain lateinit modifier?

like image 206
Michael Spitsin Avatar asked Mar 15 '17 11:03

Michael Spitsin


People also ask

What is private lateInit VAR?

The lateinit var lookupKey in Kotlin defined a property without a value set directly. The value is set to the property later. The compiler takes care to add assertions to make sure it is not possible to read the value before it is not initialized.

What is lateInit VAR in Java?

lateinit: The whole point is to make sure that we initialize the object before we use it, or else it should throw an Exception letting us know that we are missing something in the code. In the context of android, we can use this for data binding and view model objects.

What is Kotlin backing field is used for?

Backing fields The field identifier can only be used in the accessors of the property. A backing field will be generated for a property if it uses the default implementation of at least one of the accessors, or if a custom accessor references it through the field identifier.

What is a backing field C#?

A private field that stores the data exposed by a public property is called a backing store or backing field. Fields typically store the data that must be accessible to more than one type method and must be stored for longer than the lifetime of any single method.


2 Answers

You can use @JvmSynthetic that hides declarations from Java (and not from Kotlin). Just annotate the backing field of the property:

@field:JvmSynthetic
lateinit var field: String

Though the field will remain public in the bytecode, it will also have the synthetic modifier, which prevents it from being used in Java sources. However, the field seems to be still accessible through reflection at runtime.

See also: another question about @JvmSynthetic (though no definite answer there).

like image 133
hotkey Avatar answered Oct 05 '22 23:10

hotkey


The classical solution to this problem would be to use property delegation:

import kotlin.properties.Delegates

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

This code does exactly what you asked for in the question

like image 40
voddan Avatar answered Oct 06 '22 01:10

voddan