【发布时间】:2017-08-27 12:34:07
【问题描述】:
以下 Java 代码无法编译(使用 javac 1.8.0_121)
import java.util.Optional;
class B<T> {}
public class Test {
static B<Integer> f1(B<Object> a) { return null; }
static B<Integer> f2() {
Optional<B> opt = Optional.empty(); // note the raw type B
return opt.map(Test::f1).get();
// error: incompatible types: Object cannot be converted to B<Integer>
}
}
我的问题是:为什么代码不能编译如上所述,如果我将f1 更改为原始类型,为什么它会编译:
static B<Integer> f1(B a) { return null; } // program compiles with raw B
我的猜测是opt.map 被推断为返回Optional<Object>(而不是Optional<B<Integer>>),但为什么呢?我已经研究了泛型和类型擦除(JLS 4.8)的其他问题,但它们都处理在原始类型本身上调用方法时的情况(例如this)。这里,opt 不是原始的,它只需要一个原始类型参数。另外,为什么第二个版本(参数a 是原始B 而不是B<Object>)有效?
编译错误信息
Error java: incompatible types: java.lang.Object cannot be converted to B<java.lang.Integer>
【问题讨论】:
-
还能在这里添加编译错误信息吗?好吧,我错了,它在你的 cmets 里 :)
-
你能澄清一下你所说的第一版和第二版吗?
-
这个当然可以,因为它一开始就没有使用原始类型
-
Optional<B> integerB = opt.map(Test::f1); return integerB.get();这似乎也可以工作,而它的链式版本不工作return opt.map(Test::f1).get();很奇怪。 -
看起来这是 java 8 中的一个合法错误,程序编译在 java 9 early access
标签: java generics optional raw-types