@Nullable vs. Generics(Eclipse)

时间:2015-03-31 11:43:11

标签: java eclipse generics jsr305

我想将一个实用程序方法引入Java 8.名为max的方法定义如下:

@SafeVarargs
public static final <E extends Comparable<E>> E max(final E... elements) {
    E result = null; // error
    for(final E e : elements) {
        if(result == null || result.compareTo(e) < 0) {
            result = e;
        }
    }
    return result;
}

现在Eclipse显示错误:

  

空类型不匹配(类型注释):null与自由类型变量E不兼容。

我原本以为将@Nullable添加到result的定义应该会删除错误,但显然并非如此。即使我用@Nullable另外注释整个方法,错误仍然存​​在。

顺便说一句,我正在使用FindBugs中的jsr-305.jar并将Eclipse配置为荣誉javax.annotation.Nonnull以及javax.annotation.Nullable。编辑:我在Lubuntu上运行Eclipse Luna 4.4.2和Oracle JDK 8 build 1.8.0_25-b17。

现在我的问题:错误来自哪里?如何在保持注释和泛型类型定义的好处的同时摆脱它?

编辑:我刚刚添加了一个示例项目,其中使用了默认的eclipse注释,它似乎有些工作(除了在result == null生成警告,因为它错误地推断结果只能为null点)。所以这似乎是一个带有非默认注释类的Eclipse问题。我用我自己的Eclipse Nullable注释副本重新测试了它,并得到了与上面相同的错误。

2 个答案:

答案 0 :(得分:2)

  

错误来自哪里?

我在documentation

中找到了这个
  

对应于无约束类型参数的类型变量   需要悲观检查以确保所有人的安全   法律替代:这种类型既不能被认为可以为空   也不是无聊的。

class C<T extends Number> {
    int consume(T t) {
        return t.intValue(); // NOT OK since T could be nullable
    }
    T provide() {
        return null;         // NOT OK since T could require nonnull
    }
} 
     

最后一点可能看起来令人惊讶,但请注意,无约束类型参数意味着我们可能不会假设   关于由...表示的类型的null的任何事情   相应的类型变量。更重要的是:我们必须积极支持   可空和非空类型。另一方面,这只是扩展了   现有规则,唯一的类型与无界的兼容   type variable是类型变量本身。解释这种情况   在null分析的上下文中,编译器将引发以下内容   对于provide()中的返回错误:

在实例化泛型类型或调用泛型方法时,必须遵守type参数提出的约束。

  

如何在保持注释和泛型类型定义的好处的同时摆脱它?

将@Nullable添加到<E extends Comparable<E>>,就像这样

@SafeVarargs
public static final  <@Nullable E extends Comparable<E>> E max(final E... elements) {
    E result = null; // no error
    for(final E e : elements) {
        if(result == null || result.compareTo(e) < 0) {
            result = e;
        }
    }
    return result;
}

答案 1 :(得分:1)

Tja,可选。如果varargs数组为空,怎么回事?

public static final <E extends Comparable<E>> Optional<E> max(final E... elements) {
    Optional<E> result = Optional.empty();
    for(final E e : elements) {
        if(!result.isPresent() || result.get().compareTo(e) < 0) {
            result.set(e);
        }
    }
    return result;
}

或至少需要一个参数。

public static final <E extends Comparable<E>> E max(final E first, final E... elements) {
    E result = first;
    for (final E e : elements) {
        if (/*result != null ||*/ result.compareTo(e) < 0) {
            result = e;
        }
    }
    return result;
}