[英]strange issue with Generic type inference
我正在使用 Java8 的 Generics 有一个奇怪的行为。
这是一个演示问题的小示例代码以下代码可以正常工作,没有任何类型推断问题。 其中,SpecificError 是 GenericError 的子类型。
public GenericType<AbstractError> method{
Optional<SpecificError> error = Optional.of(new SpecificError());
if (error.isPresent()) {
return GenericType.error(error.get());
} else {
// return something else
}
}
我在代码中有很多这样的地方,如果/else 检查可选,我决定创建一个新的 function 接收可选,检查存在并返回通用类型 object 新 ZC1C4245268E617394F11 代码
public static <R extends AbstractError> GenericType<R> shortcut(Optional<R> error) {
if (error.isPresent()) {
return GenericType.error(error.get());
} else {
// something else
}
}
这是调用上述 function 的新代码:
public GenericType<AbstractError> method{
Optional<SpecificError> error = Optional.of(new SpecificError());
return GenericType.shortcut(error);
}
奇怪的是,这不起作用并破坏了以下编译错误:
[ERROR] inferred: AbstractError
[ERROR] equality constraints(s): AbstractError, SpecificError
我只是不明白,为什么这行不通。 唯一的事情,我做的是做一个小的function,它的工作是Present check on Optional,其他的都是一样的。 为什么 Java 看不到 SpecificError 是 AbstractError 的子类型
从方法method()
中,您正在调用GenericType.shortcut(error)
,其中error
的类型为Optional<SpecificError>
。 shortcut
需要一个类型参数R
,您正在尝试使用R = SpecificError
来实现。 所以你试图返回一个GenericType<SpecificError>
,但你的方法签名声明它返回一个GenericType<AbstractError>
。
GenericType<SpecificError>
不是GenericType<AbstractError>
,因为generics 是不变的。
你可以通过更换来解决这个问题
Optional<SpecificError> error = Optional.of(new SpecificError());
和
Optional<AbstractError> error = Optional.of(new SpecificError());
当您在shortcut()
处将 GenericType 声明为<R extends AbstractError>
它现在被迫返回一个子类型。 这就是编译器产生问题的原因。
这里见证的概念是Type Equality Constraint ,涵盖在 Java Generics
如果您将方法签名更改为
public static <R> GenericType<R> shortcut(Optional<R> error) { // remove extends AbstractError
public GenericType<AbstractError> method{
Optional<SpecificError> error = Optional.of(new SpecificError());
return GenericType.shortcut(error);
}
public static <R extends AbstractError> GenericType<R> shortcut(Optional<R> error) {
shortcut
需要一个Optional
参数,其类型参数与返回类型匹配。
但你的不是: SpecificError
与AbstractError
不同。
您只需要将error
设为R
或子类,因此为参数类型添加上限:
Optional<? extends R> error
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.