为什么 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();
我有这些 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();