Hello when I use Kotlin to program Android I have seen lateinit
in the code. What is the equivalent in java? How can I change this code from Kotlin to Java?
public class MyTest {
lateinit var subject: TestSubject
}
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.
In order to create a "lateInit" variable, we just need to add the keyword "lateInit" as an access modifier of that variable. Following are a set of conditions that need to be followed in order to use "lateInit" in Kotlin. Use "lateInit" with a mutable variable. That means, we need to use "var" keyword with "lateInit".
The “lateinit” keyword in Kotlin as the name suggests is used to declare those variables that are guaranteed to be initialized in the future. “lateinit” variable: A variable that is declared using “lateinit” keyword is known as “lateinit” variable.
The lateinit keyword allows you to avoid initializing a property when an object is constructed. If your property is referenced before being initialized, Kotlin throws an UninitializedPropertyAccessException , so be sure to initialize your property as soon as possible.
lateinit
in Kotlin is there so that you can have non-nullable types on variables that you can't initialize at the moment the class containing them is created.
Using your example, if you didn't use lateinit
, you'd have to make the subject
nullable, since it has to be initialized with a value.
public class MyTest {
var subject: TestSubject? = null
}
This would force you to do null checks every time you use it, which is ugly, so you can mark it as lateinit
instead.
In Java, you don't really have this problem, since everything is nullable, and declaring an uninitialized field is nothing special:
public class JavaTest {
TestSubject subject;
}
This initializes subject
to null
, so it's practically equivalent to the non-lateinit
Kotlin example.
The only real difference between the lateinit
version in Kotlin and the Java version is that you get a more specific exception when trying to access an uninitialized property in Kotlin, namely, a UninitializedPropertyAccessException
, which will make debugging it easier than having to look for the cause of a generic NullPointerException
.
If you really wanted this slightly different behavior, you could wrap your Java properties in some sort of wrappers, but I don't think it would be worth the syntactic overhead to do so. A very basic (not thread safe, for example) way to do this would be:
Have a generic wrapper class for properties:
public class Property<T> {
private T value = null;
public T get() {
if (value == null)
throw new UninitializedPropertyAccessException("Property has not been initialized");
return value;
}
public void set(T value) {
if (value == null)
throw new IllegalArgumentException("Value can't be null");
this.value = value;
}
}
Use this wrapper in your classes:
public class JavaTest {
Property<TestSubject> subject = new Property<>();
}
And then this usage would give you the uninitialized exception:
JavaTest test = new JavaTest();
test.subject.get();
And this one would run fine:
JavaTest test = new JavaTest();
test.subject.set(new TestSubject());
test.subject.get();
Edit: this is very similar to how lateinit
works in Kotlin, if you decompile the bytecode of your example to Java, this is what you get:
public final class MyTest {
@NotNull
public TestSubject subject;
@NotNull
public final TestSubject getSubject() {
TestSubject var10000 = this.subject;
if(this.subject == null) {
Intrinsics.throwUninitializedPropertyAccessException("subject");
}
return var10000;
}
public final void setSubject(@NotNull TestSubject var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.subject = var1;
}
}
Basically, the compiler puts the code for checking the property access inside the class itself (+ uses some helper methods) instead of using a wrapper, which is more efficient.
There is no such property in Java which delays the initialization of property. But I think the behavior in Kotlin and Java are quite similar.
Here are my two cents :
In Kotlin accessing a lateinit property before it has been initialized throws a special exception that clearly identifies the property being accessed and the fact that it hasn't been initialized. (Reference : https://kotlinlang.org/docs/reference/properties.html).
In Java also, NullPointerException(NPE) is thrown that indicated that property being accessed is Null.
The only difference could be that, NPE is a runtime exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With