3

我想给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

我原以为添加@Nullableresult应该删除错误的定义,但显然情况并非如此。即使我另外用 注释整个方法@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因为它错误地推断出结果只能在该点为空)。所以这似乎是非默认注释类的 Eclipse 问题。我用我自己的 Eclipse 注释副本重新测试了它Nullable,并得到了与上面相同的错误。

4

2 回答 2

2

错误来自哪里?

我在文档中找到了这个:

对应于不受约束的类型参数的类型变量需要进行悲观检查,以保证所有合法替换的安全性:这种类型既不能被假定为可空也不能被假定为非空。

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 分析的上下文中解释这种情况,编译器将针对 provide() 中的返回引发以下错误:

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

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

<E extends Comparable<E>>像这样添加@Nullable

@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;
}
于 2015-04-01T07:17:21.397 回答
1

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;
}
于 2015-03-31T13:06:47.377 回答