为 Supplier<? 使用 lambda 时编译失败扩展类型>
Compilation fails when using a lambda for Supplier<? extends Type>
为什么不能编译? :
import java.util.Optional;
public class Demo {
Optional<? extends SomeValue> getOption() {
return Optional.empty();
}
void exposure() {
SomeValue someValue = getOption().orElseGet(() -> new SomeValue());
}
}
class SomeValue {}
当 getOption()
将 return a Optional<SomeValue>
.
时,它可以正常工作
Optional<T>.orElseGet
被指定为接受一个 Supplier<? extends T>
。但是 Optional<? extends SomeValue>
的意思是它可能是一个 Optional<MySubClassOfSomeValue>
,在这种情况下 Supplier<SomeValue>
就不会是 Supplier<? extends MySubClassOfSomeValue>
.
orElseGet
必须 return 是 Optional
元素类型的子类型,并且 ? extends SomeValue
可以是 SomeValue
.[=20 以外的其他类型=]
这是相当受限的方法签名的结果:
public T orElseGet(Supplier<? extends T> other) {
在您的例子中,T
是 ? extends SomeValue
,这是一个未知类型,可分配给 SomeValue
(但可能是它的子类)。 orElseGet
的签名意味着允许您的供应商 return T
的子类型,具有 T
的总体结果类型,但不允许扩大到T
的通用基本类型和您的供应商类型 returns(如果您的供应商 returns SomeValue
和 T
是 ? extends SomeValue
,则常见的基本类型是 SomeValue
).
您可以通过插入允许扩大类型的操作来解决此问题:
SomeValue someValue = getOption()
.map(Function.<SomeValue>identity()).orElseGet(() -> new SomeValue());
identity
函数不改变值,但是映射操作允许传入一个消耗更广泛类型的函数,即映射函数可以在实际输入时声明消耗SomeValue
类型是 ? extends SomeValue
并且 return 类型是 SomeValue
.
但一般来说,为了避免此类问题,方法的 return 类型中不应包含通配符,因此请更改
Optional<? extends SomeValue> getOption()
至
Optional<SomeValue> getOption()
见http://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html
Using a wildcard as a return type should be avoided because it forces programmers using the code to deal with wildcards.
为什么不能编译? :
import java.util.Optional;
public class Demo {
Optional<? extends SomeValue> getOption() {
return Optional.empty();
}
void exposure() {
SomeValue someValue = getOption().orElseGet(() -> new SomeValue());
}
}
class SomeValue {}
当 getOption()
将 return a Optional<SomeValue>
.
Optional<T>.orElseGet
被指定为接受一个 Supplier<? extends T>
。但是 Optional<? extends SomeValue>
的意思是它可能是一个 Optional<MySubClassOfSomeValue>
,在这种情况下 Supplier<SomeValue>
就不会是 Supplier<? extends MySubClassOfSomeValue>
.
orElseGet
必须 return 是 Optional
元素类型的子类型,并且 ? extends SomeValue
可以是 SomeValue
.[=20 以外的其他类型=]
这是相当受限的方法签名的结果:
public T orElseGet(Supplier<? extends T> other) {
在您的例子中,T
是 ? extends SomeValue
,这是一个未知类型,可分配给 SomeValue
(但可能是它的子类)。 orElseGet
的签名意味着允许您的供应商 return T
的子类型,具有 T
的总体结果类型,但不允许扩大到T
的通用基本类型和您的供应商类型 returns(如果您的供应商 returns SomeValue
和 T
是 ? extends SomeValue
,则常见的基本类型是 SomeValue
).
您可以通过插入允许扩大类型的操作来解决此问题:
SomeValue someValue = getOption()
.map(Function.<SomeValue>identity()).orElseGet(() -> new SomeValue());
identity
函数不改变值,但是映射操作允许传入一个消耗更广泛类型的函数,即映射函数可以在实际输入时声明消耗SomeValue
类型是 ? extends SomeValue
并且 return 类型是 SomeValue
.
但一般来说,为了避免此类问题,方法的 return 类型中不应包含通配符,因此请更改
Optional<? extends SomeValue> getOption()
至
Optional<SomeValue> getOption()
见http://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html
Using a wildcard as a return type should be avoided because it forces programmers using the code to deal with wildcards.