Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin lateinit correspondent java

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
}
like image 891
undervoid Avatar asked Mar 22 '17 23:03

undervoid


People also ask

What is Lateinit 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.

How do you initialize Lateinit property in Kotlin?

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".

How do I declare a Lateinit variable in Kotlin?

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.

How does Kotlin define Lateinit?

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.


2 Answers

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.

like image 179
zsmb13 Avatar answered Oct 20 '22 13:10

zsmb13


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.

like image 23
Sagar Jani Avatar answered Oct 20 '22 12:10

Sagar Jani