不知道大家在使用Kotlin进行编码的时候,有没有直接使用AS的Code -> Convert Java File 2 Kotlin File
这个功能,此功能在日常使用中还是比较实用的,可以帮助我们将老的Java或者复制的Java代码一键转换成Kotlin代码,最近在使用此功能的时候竟然遇到了空指针的Crash,在此记录一下,顺便也给大家做个预警。
起因
在工程中引入了三方的SDK,此SDK使用Java编码,我们需要实现它的一个回调方法做一下异常处理,SDK具体方法就不贴出来了,下面模拟一下他们的回调
public class Test {
// 定义回调接口,其中error用来处理异常情况,参数为Exception对象
public interface TestCallback {
void test();
void error(Exception e);
}
// 传入回调并直接模拟调用它的方法
public void setTest(TestCallback testCallback) {
testCallback.test();
testCallback.error(new Exception("test"));
}
}
模拟了它们的回调接口,然后在setTest(callback)
中直接调用接口方法,这里先看一下这个error
的接口方法,它的参数exception
并没有使用可空(@Nullable
)或者非空(@NonNull
)注解来定义,默认就是可空类型。
然后我们直接模拟调用下看看具体效果,先用Java代码来调用
public class Java2Kt {
private final Test testCallback = new Test();
public void test() {
testCallback.setTest(new Test.TestCallback() {
@Override
public void test() {
Log.d("taonce", "Java2Kt test");
}
@Override
public void error(Exception e) {
if (e != null) {
Log.d("taonce", "Java2Kt error " + e.getMessage());
}
}
});
}
}
#
Java2Kt test
Java2Kt error java.lang.Exception: custom exception
这样就没得毛病,可以正确调用并输出日志,然后我们改一下setTest(callback)
方法,再额外添加一行
public void setTest(TestCallback testCallback) {
testCallback.test();
testCallback.error(new Exception("test"));
// 新增
testCallback.error(null);
}
即使我们在error()
调用的地方传入null
也不会出现什么问题,因为我们在回调实现的时候加入了非空判断,但是我们使用Convert Java File 2 Kotlin File
转换成Kotlin之后再看看代码
class Java2Kt {
private val testCallback = Test()
fun test() {
testCallback.setTest(object : TestCallback {
override fun test() {
Log.d("taonce", "Java2Kt test")
}
override fun error(e: Exception) {
if (e != null) {
Log.d("taonce", "Java2Kt error " + e.message)
}
}
})
}
}
这样乍一看是不会出现问题的,因为转换成KT之后,非空判断也是有的,但是此时AS会在非空判断的地方报警告,提示我们Condition 'e != null' is always 'true'
,习惯性的就会将这个非空给去掉,去掉之后一运行直接来了一个空指针异常
分析
AS的Convert Java File 2 Kotlin File
功能在转换过程中,如果参数未使用可空或者非空注解,转换之后默认是非空类型,这样就会导致我们在使用的时候不太注意此参数的可空类型,有时会丢掉可空检查,这样在程序运行的过程中就会出现空指针的可能,再来看看直接使用KT实现回调的代码
test.setTest(object : Test.TestCallback {
override fun test() {
Log.d("taonce", "MainActivity test")
}
// 默认为可空类型
override fun error(e: Exception?) {
Log.d("taonce", "MainActivity test ${e?.stackTraceToString()}")
}
})
如果直接使用KT来编码,实现TestCallback
的时候error(exception?)
是默认加上了可空(?)的,很明确的告知开发者需要注意此参数可能为空,需要在使用的时候加上可空判断。所以直接使用KT是大概率的不会出现空指针的情况了。
小结
- AS的
Convert Java File 2 Kotlin File
功能固然是给开发者提供了便捷的操作,但是也需要开发者使用之后谨慎判断 - 对于自己使用Java写的一些回调,尽可能的加上可空或者非空的注解,可以给调用者提供一些警示信息
- 在日常编码中,编码细节一定要处理得当,空指针无可避免但也需要最大化的避免此种异常,KT在这方面已经为开发者提供了较为安全的操作了
标签:Convert,Java,Kotlin,error,可空,testCallback,test From: https://blog.51cto.com/u_16163442/6512806