Kotlin Lateinit通讯Java [英] Kotlin lateinit correspondent java
问题描述
你好,当我使用Kotlin对Android进行编程时,我在代码中看到了lateinit
. java中的等效语言是什么?如何将该代码从Kotlin更改为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
}
在Kotlin中的
推荐答案
lateinit
在那里,您可以在不包含变量的类中创建非空类型,这些变量在创建包含它们的类时无法初始化
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.
使用您的示例,如果您不使用lateinit
,则必须使subject
可为空,因为必须使用值对其进行初始化.
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
}
这将迫使您每次使用它时都要执行空检查,这很丑陋,因此您可以将其标记为lateinit
.
This would force you to do null checks every time you use it, which is ugly, so you can mark it as lateinit
instead.
在Java中,您实际上没有这个问题,因为所有内容都是可为空的,并且声明未初始化的字段没什么特别的:
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;
}
这会将subject
初始化为null
,因此实际上与非lateinit
Kotlin示例相同.
This initializes subject
to null
, so it's practically equivalent to the non-lateinit
Kotlin example.
Kotlin中的lateinit
版本与Java版本之间的唯一真正区别是,当您尝试访问Kotlin中的未初始化属性(即UninitializedPropertyAccessException
)时,会得到一个更具体的异常,这将使调试更加容易不必寻找通用NullPointerException
的原因.
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
.
如果您确实想要这种略有不同的行为,则可以将Java属性包装在某种包装中,但是我认为这样做不值得在语法上开销.一个非常基本的方法(例如,不是线程安全的)可以做到这一点:
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();
这将运行良好:
JavaTest test = new JavaTest();
test.subject.set(new TestSubject());
test.subject.get();
这与lateinit
在Kotlin中的工作方式非常相似,如果将示例的字节码反编译为Java,那么您将得到:
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.
这篇关于Kotlin Lateinit通讯Java的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!