本文介绍Facebook推出的静态代码检查工具Infer,用于检查代码中的空指针异常。
IDEA中提供了Infer Nullity静态代码检查工具,可用于分析Java代码中的潜在的NullPointerException。
注:Nullity检查不局限于Java,但本文只讨论Java。
一个变量的声明(或方法的参数、返回值),可以使用Nullity注解,分别表示变量可能为空、永远非空。
org.jetbrains.annotations.Nullable org.jetbrains.annotations.NotNull
被注解的变量,通过Nullity检查可以有效避免NullPointerException异常,例如:
除了使用IDEA自带的注解,IDEA也支持指定其他注解,例如Android开发时,可以使用Android的Nullity注解代替:
<a href="http://www.paincker.com/tag/android" rel="tag" title="Posts tagged with Android">android</a>.support.annotation.Nullable <a href="http://www.paincker.com/tag/android" rel="tag" title="Posts tagged with Android">android</a>.support.annotation.NonNull
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中效果如下
class Test { @Nullable Object nullable; // NonNull变量应该在类初始化时赋非空值 @NonNull Object nonnull; void f1() { // NonNull参数不能传空值 f(null); // NonNull参数不能传可能为空的值 f(nullable); } void f(@NonNull Object nonnullArg) { // NonNull变量不必要的判空 if (nonnullArg == null) { } // Nullable变量没做判空 String s = nullable.toString(); } } class SubClass extends Test { // 继承的方法,参数没加NonNull注解 void f(Object nonnullArg) { } }
可以在IDEA / Android Studio中,通过Infer Nullity功能检查。
由于Java代码中,并不一定所有变量都有Nullity标注,因此Nullity检查并不完全可靠。例如给NonNull变量赋一个可能为空、但没有Nullity标注的成员变量,并不一定能检查出来问题。
例如:
class A { Object a; Object b; void f(@NonNull Object nonnullArg) { } void test() { // 这里检查不出来问题,因为a没有Nullity注解,也没法从上下文判断a是否可能为空 f(a); // 这里可以检查出问题,因为可以从上下文推断出b可能为空 b = null; f(b); } }
在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:
var a: String = "abc" a = null // compilation error
如果一个变量可能为空,则需要加一个问号如下。
To allow nulls, we can declare a variable as nullable string, written String?:
var b: String? = "abc" b = null // ok
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.htmlAndroid Studio – Infer Nullity?
https://stackoverflow.com/questions/22641830/android-studio-infer-nullityInferring Nullity
https://www.jetbrains.com/help/idea/inferring-nullity.htmlAndroid注解支持(Support Annotations)
http://www.flysnow.org/2015/08/13/android-tech-docs-support-annotations.html最后,欢迎扫码关注微信公众号,也可以加我微信 jzj2015 交流(注明来自博客)。