为什么 Java 可选类型信息丢失?

Why is Java Optional type information lost?

我有这些 class 方法:

public abstract class Bar<T extends Bar> {
    Foo myFoo;
    public Optional<Foo> findFoo() { return Optional.ofNullable(this.myFoo); }
}

public class Baz extends Bar<Baz> {
}

,其中 Foo 是一个具体的 final class,o 是一个扩展 Bar 的对象。

可以这样在我的单元测试中获取值:

Bar bar = new Baz();
Optional<Foo> optinalFoo =  bar.findFoo();
Foo foo = optionalFoo.get();

但是,当直接调用时类型信息丢失:

Foo foo = bar.findFoo().get();

在第二个例子中,编译器认为 get() returns 是一个 Object 而不是 Foo。为什么?有没有办法以其他方式向编译器提供类型信息?

(我知道你应该避免直接调用 get() 但因为这是在单元测试中,如果它抛出意外结果也没关系。)

Bar bar 是原始类型。原始类型没有任何通用信息,它是一个全有或全无的东西。没有一个很好的、通用的回退。一个例子是

Map<String, String> map = new HashMap<>();
Set<Map.Entry<String, String>> entries = map.entrySet();

// however when you use a raw type there is no generic.
Map map2 = new HashMap();
Set<Map.Entry> entries2 = map2.entrySet(); // doesn't work
Set entries2 = map2.entrySet(); // does work

这是因为提供原始类型只是为了向后兼容。在 Java 5.0 之前的版本中没有泛型,因此您不得不期望原始类型没有任何泛型。

bar 变量使用原始类型,因此它缺少所有通用类型检查。定义类型 Optional<Foo> optionalFoo 你也有未经检查的分配(这意味着类型将被检查 运行-time only),但编译器看到类型并且 .get() 工作正常。要修复,您需要定义通用参数,例如

Bar<? extends Bar> bar = new Baz();