验证变量空警告

Validated variable null warning

在 Eclipse (4.7.2) 中 null analysis -> potential null access 设置为给我一个警告。

给定以下代码:

public class Test {

    // validator method
    static boolean hasText(String s) {
        return !(s == null || s.trim().isEmpty());
    }

    public static void main(String[] args) {
        // s could come from anywhere and is null iff the data does not exist
        String s = (new Random().nextBoolean()) ? "valid" : null;
        if (hasText(s)) {
            // Potential null pointer access: The variable s may be null at this location
            System.out.println(s.length());
            // ... do actual stuff ...
        }
    }
}

如何避免潜在的空警告? @NotNull 将不起作用,因为 null 是有效输入,输出是 boolean.

有没有办法告诉编译器,如果此验证方法 returns 为真,则验证值不为空?

有没有更好的方法来处理这样的验证方法?

谢谢。


为清楚起见更新:

数据来自用户输入(来自 xml 或 .properties 文件)并且如果数据确实存在则为空。

从不生成 null(例如,将其设置为 "")会发明不存在的数据,而且我不能完全拥有一个 NullString 对象(可以' t 扩展 String) 来表示不存在的数据。

hasText(String s) 必须能够接受任何此输入数据,因此必须能够接受 null.

这个怎么样?

public class Test {

    // validator method
    private static boolean hasText(String s) {
        return s != null && !s.trim().isEmpty();
    }

    public static void main(String[] args) {
        String s = (new Random().nextBoolean()) ? "valid" : null;
        if (s != null && hasText(s)) {
            System.out.println(s.length());
            // ... do actual stuff ...
        }
    }
}

有了这个,您可以将 hasText(String) 方法简化为:

    // validator method
    private static boolean hasText(String s) {
        return !s.trim().isEmpty();
    }

另一种选择是避免产生 null 值:

public class Test {

    // validator method
    private static boolean hasText(String s) {
        return !s.trim().isEmpty();
    }

    public static void main(String[] args) {
        String s = (new Random().nextBoolean()) ? "valid" : "";
        if (hasText(s)) {
            System.out.println(s.length());
            // ... do actual stuff ...
        }
    }
}

您的代码是安全的(它永远不会抛出空指针异常),但 Eclipse 的分析可能太弱而无法确定这一点。您应该考虑使用更强大的工具。

Checker Framework's Nullness Checker可以证明你的代码是安全的。你只需要表达 hasText 的契约: hasText 接受一个 possibly-null 参数,并且它 returns 只有当它的参数是 non-null.[=16 时才为真=]

表达方式如下:

@EnsuresNonNullIf(expression="#1", result=true)
static boolean hasText(@Nullable String s) { ... }

(更多详细信息,请参阅 Javadoc for @EnsuresNonNullIf。)

这是您的完整示例,Nullness Checker 会在没有警告的情况下对其进行验证:

import java.util.Random;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;

public class Test {

    // validator method
    @EnsuresNonNullIf(expression="#1", result=true)
    static boolean hasText(@Nullable String s) {
        return !(s == null || s.trim().isEmpty());
    }

    public static void main(String[] args) {
        // s could come from anywhere and is null iff the data does not exist
        String s = (new Random().nextBoolean()) ? "valid" : null;
        if (hasText(s)) {
            // Potential null pointer access: The variable s may be null at this location
            System.out.println(s.length());
            // ... do actual stuff ...
        }
    }
}