为什么这不编译?:
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()返回一个Optional<SomeValue>时,它可以正常工作。
发布于 2015-03-17 17:40:26
这是一个相当有限的方法签名的结果:
public T orElseGet(Supplier<? extends T> other) {在您的例子中,T是? extends SomeValue,它是一个未知类型,可以分配给SomeValue (但可能是它的一个子类)。orElseGet的签名意味着允许您的供应商返回一个T的子类型,其总体结果类型为T,但它不允许对公共基本类型的T和供应商返回的类型进行扩展(如果供应商返回SomeValue,而T为? extends SomeValue,则公共基类型将为SomeValue)。
可以通过插入允许拓宽类型的操作来修复此问题:
SomeValue someValue = getOption()
.map(Function.<SomeValue>identity()).orElseGet(() -> new SomeValue());identity函数不会更改值,但是映射操作允许传入一个消耗更广泛类型的函数,即当实际输入类型为? extends SomeValue而返回类型为SomeValue时,映射函数可以声明使用? extends SomeValue。
但是通常情况下,为了避免此类问题,方法的返回类型中不应该有通配符,所以请更改。
Optional<? extends SomeValue> getOption()至
Optional<SomeValue> getOption()请参阅http://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html
应该避免使用通配符作为返回类型,因为它迫使使用代码的程序员处理通配符。
发布于 2015-03-17 16:59:54
指定Optional<T>.orElseGet以接受Supplier<? extends T>。但Optional<? extends SomeValue>的含义是,它可以是Optional<MySubClassOfSomeValue>,在这种情况下,Supplier<SomeValue>不会是Supplier<? extends MySubClassOfSomeValue>。
orElseGet必须返回Optional元素类型的子类型,而? extends SomeValue可能不是SomeValue。
https://stackoverflow.com/questions/29104218
复制相似问题