简体   繁体   English

@Nullable vs. Generics(Eclipse)

[英]@Nullable vs. Generics (Eclipse)

I want to bring a utility method to Java 8. The method named max is defined as follows: 我想将一个实用程序方法引入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;
}

Now Eclipse shows an error: 现在Eclipse显示错误:

Null type mismatch (type annotations): null is not compatible to the free type variable E . 空类型不匹配(类型注释): null与自由类型变量E不兼容。

I would have thought that adding @Nullable to the definition of result should remove the error, but this is apparently not the case. @Nullable以为将@Nullable添加到result的定义应该删除错误,但显然不是这种情况。 Even if I additionally annotate the whole method with @Nullable , the error persists. 即使我另外使用@Nullable注释整个方法,错误仍然存​​在。

By the way I'm using jsr-305.jar from FindBugs and have configured Eclipse to honor javax.annotation.Nonnull as well as javax.annotation.Nullable . 顺便说一句,我正在使用FindBugs的jsr-305.jar,并已配置Eclipse以尊重javax.annotation.Nonnull以及javax.annotation.Nullable Edit: I run Eclipse Luna 4.4.2 and Oracle JDK 8 build 1.8.0_25-b17 on Lubuntu. 编辑:我在Lubuntu上运行Eclipse Luna 4.4.2和Oracle JDK 8 build 1.8.0_25-b17。

Now for my question: Where does the error come from? 现在我的问题是:错误来自哪里? How do I get rid of it while maintaining the benefit of both the annotation and the generic type definition? 如何在保持注释和泛型类型定义的好处的同时摆脱它?

Edit: I just added an example project where the default eclipse annotations are used, and it appears to somewhat work (apart from generating a warning at the result == null because it incorrectly infers that result can only be null at that point). 编辑:我刚刚添加了一个示例项目,其中使用了默认的eclipse注释,它似乎有些工作(除了在result == null处生成警告,因为它错误地推断结果在该点只能为null)。 So this appears to be an Eclipse problem with non-default annotation classes. 所以这似乎是一个带有非默认注释类的Eclipse问题。 I re-tested it with my own copy of Eclipse's Nullable annotation, and got the same error as above. 我用我自己的Eclipse的Nullable注释副本重新测试它,并得到与上面相同的错误。

Where does the error come from? 错误来自哪里?

I found this in the 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. 最后一点可能看起来令人惊讶,但请注意,无约束类型参数意味着我们可能不会假设任何关于由相应类型变量表示的类型的null。 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(): 要在null分析的上下文中解释这种情况,编译器将针对provide()中的返回引发以下错误:

When instantiating a generic type or when invoking a generic method, the constraints put forward by the type parameter must be observed. 在实例化泛型类型或调用泛型方法时,必须遵守type参数提出的约束。

How do I get rid of it while maintaining the benefit of both the annotation and the generic type definition? 如何在保持注释和泛型类型定义的好处的同时摆脱它?

Add @Nullable to <E extends Comparable<E>> , like so 将@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;
}

Tja, Optional. Tja,可选。 How else if the varargs array is empty? 如果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;
}

Or require at least one argument. 或者至少需要一个参数。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM