如何让IntelliJ IDEA了解我的空检查方法?

时间:2012-05-17 13:16:44

标签: java intellij-idea nullable

我有一个方法,其中参数用@Nonnull注释标记。调用该方法的代码必须检查该值是否为null。它不是直接x != null检查,而是在另一个类上调用实用程序方法。 (在实际代码中,实用程序方法还会检查它是否为空字符串。)

我的问题是Intellij Idea在Nonnull方法调用上显示检查警告,说我的变量“可能为null”。我知道它不能为空因为实用方法检查 - 我该如何告诉检查员?

因为这有点抽象,所以这是我的意思的最小例子:

package org.ethelred.ideatest;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;

/**
 * tests annotations
 */
public class AnnotationChecker
{
    public static void main(String[] args)
    {
        String x = null;
        if(args.length > 0)
        {
            x = args[0];
        }

        if(!isNull(x))
        {
            useObject(x);
        }

        if(x != null)
        {
            useObject(x);
        }
    }

    public static boolean isNull(@CheckForNull Object o)
    {
        return o == null;
    }


    public static void useObject(@Nonnull Object o)
    {
        System.out.println(o);
    }
}

这使用JSR 305注释。

在此示例中,在第一次useObject的调用中,Intellij对x参数发出警告,说“参数'x'可能为空”。在第二次调用中,没有警告。

4 个答案:

答案 0 :(得分:7)

在IDEA 13中添加了一个非常奇特的功能,称为Method Contracts。例如,您可以使用一个方法,如果遇到null,则抛出验证异常:

@Contract("null -> fail")
public static void validateNull(@Nullable final Object object) {
    if (object == null) {
        throw new ValidationException();
    }
}

如果您在可能的NPE之前调用注释,IDEA将分析注释并且不会显示警告:

validateNull(user);
user.setSomething("something"); // no warning

您在IDEA的设置中拥有完整的文档(只需搜索方法合约)。为此,您需要额外依赖jetb​​rain的注释jar:

<dependency>
    <groupId>org.jetbrains</groupId>
    <artifactId>annotations</artifactId>
    <version>13.0</version>
</dependency>

答案 1 :(得分:5)

使用IDEA 12,您可以配置NotNull检查方法: http://youtrack.jetbrains.com/issue/IDEA-35808#tab=Comments

答案 2 :(得分:3)

我不相信有任何方法可以用编写的代码来解决警告。我希望发现IntelliJ支持@SuppressWarnings可以在useObject(x)语句中使用的值,但根据this source,它不支持。if (x != null && !isBlank(x)) { useObject(x); } 。您可能只需咬紧牙关并将代码更改为以下内容:

isNull

请注意,我已将方法isBlank重命名为null,因为我理解您正在调用的实际方法检查{{1}}也会检查其他条件。< / p>

答案 3 :(得分:-1)

我通过使用静态方法将对象调用列入白名单来解决此问题:

/** Wrapper to mask NullPointerException warnings. */
private static <T> T _(T obj) {

    return obj;
}

方法名称旨在不干扰可读性。因此,

mObject.method();

变为

_(mObject).method();

此外,如果确实发生NullPointerException,它仍然会引用相同的行号。