@Nullable 与泛型 (Eclipse)

@Nullable vs. Generics (Eclipse)

我想带一个实用方法给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 type mismatch (type annotations): null is not compatible to the free type variable E.

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

顺便说一句,我使用的是 FindBugs 中的 jsr-305.jar,并已将 Eclipse 配置为支持 javax.annotation.Nonnulljavax.annotation.Nullable。编辑:我 运行 Eclipse Luna 4.4.2 和 Oracle JDK 8 在 Lubuntu 上构建 1.8.0_25-b17。

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

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

Tja,可选。如果可变参数数组为空怎么办?

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;
}

Where does the error come from?

我在 documentation 中找到了这个:

A type variable corresponding to an unconstrained type parameter requires pessimistic checking in order to guarantee safety with all legal substitutions: this type can neither be assumed to be nullable nor nonnull.

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

The last point may look surprising at first, but please see that an unconstrained type parameter implies that we may not assume anything about the nullness of the type represented by the corresponding type variable. Even more: we must actively support nullable and nonnull types. On the other hand this simply extends the existing rule that the only type being compatible with an unbounded type variable is the type variable itself. To explain this situation in the context of null analysis, the compiler will raise the following error against the return in provide():

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

How do I get rid of it while maintaining the benefit of both the annotation and the generic type definition?

将@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;
}