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。