例子
lateinit 是kotlin的关键字,和var一起使用,用来声明一个不可空的不用立刻赋值的变量。通常用法是:
private lateinit var mScore: TextViewfun init(view: View) { 美国高防vps mScore = view.findViewById(R.id.score)}fun updateScore(score: Int) { mScore.text = “分数为:$score”}
相对于val和var而言,有几个好处:
不用立刻赋值;跟 val 相比,可以反复赋值;跟延后赋值的 var 相比,使用时不用到处加 ? 或 !!。 Java实现
我们先将上面例子中的代码用java写下:
private TextView mScore; public void init(View view) { mScore = view.findViewById(id.score); } public final void updateScore(int score) { mScore.setText((CharSequence)(“分数为:” + score)); }
再通过 Android Studio 的 show kotlin bytecode 工具,将例子中的kotlin转化成 java ,会发现这个代码跟我们用java代码写的挺像的。
private TextView mScore; public final void init(@NotNull View view) { Intrinsics.checkParameterIsNotNull(view, “view”); View var10001 = view.findViewById(id.score); Intrinsics.checkExpressionValueIsNotNull(var10001, “view.findViewById(R.id.score)”); this.mScore = (TextView)var10001; } public final void updateScore(int score) { TextView var10000 = this.mScore; if (var10000 == null) { Intrinsics.throwUninitializedPropertyAccessException(“mScore”); } var10000.setText((CharSequence)(“分数为:” + score)); }
去掉烦人的Intrinsics 的 checkParameterIsNotNull 、checkExpressionValueIsNotNull、throwUninitializedPropertyAccessException,那就是完全一样了!
可以推断 lateinit var 是一个为了照顾我们java写法习惯而创建关键词。
深入一点
看下 kotlin 生成的 java updateScore()方法,在 mScore 变量使用前,会先检查下是否为空,如果为空,会抛出异常:UninitializedPropertyAccessException。
public static void throwUninitializedPropertyAccessException(String propertyName) { throwUninitializedProperty(“lateinit property ” + propertyName + ” has not been initialized”); }
这就是我们在使用lateinit时会遇到的:lateinit property *** has not been initialized 异常。
因此:在使用lateinit var声明的变量前,一定保证变量被初始化了!
那有没有能检测 lateinit var的变量是否被初始化的方法呢?
答案是有,那就是使用lateinit var 变量的 isInitialized 属性。
fun updateScore(score: Int) { if (::mScore.isInitialized) { mScore.text = “分数为:$score” } }
转化成java是:
public final void updateScore(int score) { if (((Test)this).mScore != null) { TextView var10000 = this.mScore; if (var10000 == null) { Intrinsics.throwUninitializedPropertyAccessException(“mScore”); } var10000.setText((CharSequence)(“分数为:” + score)); } }
可以看到isInitialized的实现其实是做了判空,如果不为空,才去使用。果然比较符合java的习惯。
建议
避免使用lateinit var。因为非常容易出现“lateinit property *** has not been initialized”的异常。如果到处使用isInitialized,又会让代码会变得冗余。推荐 val 和var 搞定一切哈。
57793411