11

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

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

因为这有点抽象,所以这里有一个最小的例子来说明我的意思:

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 注释。

在此示例中,在对Intellij的第一次调用中,会在参数上显示“Argument 'x' might be null”的警告。在第二次调用中,没有警告。useObjectx

4

4 回答 4

11

在 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 的设置中有完整的文档(只需搜索 Method Contract)。为此,您需要额外依赖 jetbrain 的注释 jar:

<dependency>
    <groupId>org.jetbrains</groupId>
    <artifactId>annotations</artifactId>
    <version>13.0</version>
</dependency>
于 2015-07-29T16:14:09.910 回答
5

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

于 2013-06-14T06:24:22.273 回答
4

我不相信有任何方法可以使用按原样编写的代码来解决警告。我希望发现 IntelliJ 支持@SuppressWarnings您可以在useObject(x)语句中使用的值,但根据此来源,它不支持。您可能只需要硬着头皮将代码更改为以下内容:

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

请注意,我将该方法重命名为isNullisBlank因为我的理解是,您调用的实际方法也会null检查其他条件。

于 2012-05-17T13:51:51.880 回答
-1

我已经通过使用静态方法将对象调用列入白名单来处理此问题:

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

    return obj;
}

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

mObject.method();

变成

_(mObject).method();

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

于 2012-10-17T21:37:50.413 回答