Kotlin lateinit记者java

你好,当我使用Kotlin来编程Android我已经看到在代码中的lateinit 。 java中的等价物是什么?我怎么把这个代码从Kotlin改成Java?

 public class MyTest { lateinit var subject: TestSubject } 

在Kotlin的lateinit是那里,所以你可以有不可初始化的variablestypes的variables,在包含它们的类被创建的时候你不能初始化。

使用你的例子,如果你没有使用lateinit ,你必须使subject空,因为它必须用值初始化。

 public class MyTest { var subject: TestSubject? = null } 

这会迫使你每次使用它都lateinit检查,这很丑,所以你可以把它标记为lateinit


在Java中,你并不是真的有这个问题,因为一切都是可以空的,而声明一个未初始化的字段没有什么特别的:

 public class JavaTest { TestSubject subject; } 

这将subject初始化为null ,所以它实际上相当于非lateinit Kotlin示例。

Kotlin的lateinit版本和Java版本之间唯一真正的区别是当你试图访问Kotlin中的一个未初始化的属性时,你会得到一个更具体的exception,即一个UninitializedPropertyAccessException ,这将使得调试比查找原因更容易通用的NullPointerException


如果你真的想要这个稍微不同的行为,你可以把你的Java属性封装在某种包装器中,但是我不认为这样做是值得的。 一个非常基本的(例如不是线程安全的)方法是:

有一个属性的通用包装类:

 public class Property { 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; } } 

在你的类中使用这个包装:

 public class JavaTest { Property subject = new Property<>(); } 

然后这个用法会给你未初始化的exception:

 JavaTest test = new JavaTest(); test.subject.get(); 

而这一个将运行良好:

 JavaTest test = new JavaTest(); test.subject.set(new TestSubject()); test.subject.get(); 

编辑:这和Kotlin中的lateinit工作非常相似,如果您将示例的字节码反编译为Java,那么您将得到:

 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, ""); this.subject = var1; } } 

基本上,编译器将检查属性访问的代码放入类本身(+使用一些辅助方法),而不是使用包装器,这是更有效的。

Java中没有这样的属性来延迟属性的初始化。 但是我认为Kotlin和Java的行为是非常相似的。

这是我的两分钱:

在Kotlin访问一个lateinit属性之前,它已经被初始化抛出一个特殊的exception,清楚地标识被访问的属性以及它没有被初始化的事实。 (参考: https : //kotlinlang.org/docs/reference/properties.html )。

在Java中,也抛出了NullPointerException(NPE),表明被访问的属性是Null。

唯一的区别可能是,NPE是一个运行时exception。