您的浏览器不支持CSS3,建议使用Firfox、Chrome等浏览器,以取得最佳显示效果

空指针静态代码检查工具Infer

开发技术 1,090℃ 0 8个月前 (01-17)

摘要

本文介绍Facebook推出的静态代码检查工具Infer,用于检查代码中的空指针异常。

基本介绍

IDEA中提供了Infer Nullity静态代码检查工具,可用于分析Java代码中的潜在的NullPointerException。

注:Nullity检查不局限于Java,但本文只讨论Java。

一个变量的声明(或方法的参数、返回值),可以使用Nullity注解,分别表示变量可能为空、永远非空。

org.jetbrains.annotations.Nullable
org.jetbrains.annotations.NotNull

被注解的变量,通过Nullity检查可以有效避免NullPointerException异常,例如:

  • 读变量:当调用Nullable注解的变量时,如果不对其进行判空,IDEA就会有警告;调用NotNull注解的变量,如果对其进行不必要的判空也会产生警告。
  • 写变量:NotNull注解的成员变量,如果在类构造时没有为其赋非空值,就会报错。给NotNull注解的变量赋值(或调用函数传参)时,如果所赋值可能为空,也会报错。
  • 方法中NonNull注解的参数,子类继承时也要有NonNull注解。

指定注解

除了使用IDEA自带的注解,IDEA也支持指定其他注解,例如Android开发时,可以使用Android的Nullity注解代替:

android.support.annotation.Nullable
android.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功能检查。

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中的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:

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.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

最后,欢迎扫码关注微信公众号。微软 / Shopee / Coupang / BAT等国内外企业内推、行业和技术交流,也可以加我微信 jzj2015(注明来自博客),拉你进技术群。

本文由原创,转载请注明来源:https://www.paincker.com/infer
(标注了原文链接的文章除外)

0

暂无评论

评论前:需填写以下信息,或 登录

用户登录

忘记密码?