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

时间:2017-04-24 08:24:16

标签: java optional type-inference

我有这些类的方法:

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是具体的最终类,o是扩展Bar的对象。

可以通过这种方式获得单位测试中的值:

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

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

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

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

(我知道你应该避免直接调用get(),但由于这是在单元测试中,如果它会引发意外结果,那就没关系。)

2 个答案:

答案 0 :(得分:0)

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之前的版本中没有泛型,因此您不得不期望原始类型没有任何泛型。

答案 1 :(得分:0)

bar变量使用原始类型,因此它缺少所有泛型类型检查。定义类型Optional<Foo> optionalFoo您还有未经检查的赋值(这意味着类型将仅在运行时检查),但编译器会看到类型,.get()工作正常。要解决此问题,您需要定义通用参数,例如:

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