2017-04-24 91 views
-2

我有这些类与方法:为什么Java可选类型信息丢失?

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 = new Baz(); 
Optional<Foo> optinalFoo = bar.findFoo(); 
Foo foo = optionalFoo.get(); 

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

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

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

(我知道你应该避免直接调用get(),但由于这是一个单元测试它,如果它抛出的意想不到的结果是好的。)

+3

问题寻求帮助调试(“为什么不是这个代码的工作?”)必须包括所期望的行为,一个特定的问题或错误,并重现它在问题本身所需要的最短的代码。没有明确问题陈述的问题对其他读者无益。请参阅:如何创建[mcve]。具体来说:什么是** o **? – GhostCat

+4

'Foo'是泛型还是具体类型? “用某种方法进行某些课程”对于我们理解问题或重现问题来说,描述不够。 –

+1

由于'return.ofNullable',它不会编译。这是什么意思? – Andrew

回答

0

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

Bar<? extends Bar> bar = new Baz(); 
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之前的版本中没有泛型,所以你不得不期待raw类型没有任何泛型。

相关问题