基本介绍
IDEA中提供了Infer Nullity静态代码检查工具,可用于分析Java代码中的潜在的NullPointerException。
注:Nullity检查不局限于Java,但本文只讨论Java。
一个变量的声明(或方法的参数、返回值),可以使用Nullity注解,分别表示变量可能为空、永远非空。
1 | org.jetbrains.annotations.Nullable |
被注解的变量,通过Nullity检查可以有效避免NullPointerException异常,例如:
- 读变量:当调用Nullable注解的变量时,如果不对其进行判空,IDEA就会有警告;调用NotNull注解的变量,如果对其进行不必要的判空也会产生警告。
- 写变量:NotNull注解的成员变量,如果在类构造时没有为其赋非空值,就会报错。给NotNull注解的变量赋值(或调用函数传参)时,如果所赋值可能为空,也会报错。
- 方法中NonNull注解的参数,子类继承时也要有NonNull注解。
指定注解
除了使用IDEA自带的注解,IDEA也支持指定其他注解,例如Android开发时,可以使用Android的Nullity注解代替:
1 | android.support.annotation.Nullable |
Android Studio中默认已经配置了Android的Nullity注解。其他环境下,配置方法可以参考:
More flexible and configurable @Nullable/@NotNull annotations https://blog.jetbrains.com/idea/2011/03/more-flexible-and-configurable-nullublenotnull-annotations/
示例代码
示例代码和在Android Studio中效果如下
1 | class Test { |
检查
可以在IDEA / Android Studio中,通过Infer Nullity功能检查。
Nullity的问题
由于Java代码中,并不一定所有变量都有Nullity标注,因此Nullity检查并不完全可靠。例如给NonNull变量赋一个可能为空、但没有Nullity标注的成员变量,并不一定能检查出来问题。
例如:
1 | class A { |
Kotlin中的Null Safety
在Kotlin中,每个变量定义时,都需要声明是否可能为空。
如果声明变量时,不写问号如下,则变量为NotNull型,不可为空。
In Kotlin, the type system distinguishes between references that can hold null (nullable references) and those that can not (non-null references). For example, a regular variable of type String can not hold null:
1 | var a: String = "abc" |
如果一个变量可能为空,则需要加一个问号如下。
To allow nulls, we can declare a variable as nullable string, written String?:
1 | var b: String? = "abc" |
Kotlin从语法层面,强制所有变量都要声明为NotNull或Nullable类型。这样通过Nullity检查,代码就不会发生NullPointerException了。
如果将Kotlin代码编译后再反编译成Java,也可以看到其中就是给每个变量使用了Nullity注解。
实现
Infer Nullity检查是由FaceBook开发的静态代码检查工具Infer实现的,可以在命令行执行Infer实现Nullity检查。
Infer http://fbinfer.com/
参考
Android代码重构实战 http://www.10tiao.com/html/209/201706/2651113422/1.html
Android Studio - Infer Nullity? https://stackoverflow.com/questions/22641830/android-studio-infer-nullity
Inferring Nullity https://www.jetbrains.com/help/idea/inferring-nullity.html
Android注解支持(Support Annotations) http://www.flysnow.org/2015/08/13/android-tech-docs-support-annotations.html