为什么以下不起作用?void execute() { Integer a = Integer.valueOf(1); a = reassign(a); D.log("a: " + a);}<T extends Integer> T reassign(T t) { t = Integer.valueOf(2); // error: incompatible types: Integer cannot be converted to T // t = (T) Integer.valueOf(2); // This works but with warning: [unchecked] unchecked cast return t;}<T extends Integer> T reassign2(T t, T anotherT) { t = anotherT; // This works without any warning. return t;}我的理解是,通用方法/类/接口将被编译为单个类文件,其中类型参数被替换为最合适的下限(在上述情况下为整数)。Java 环境:java 11.0.4 2019-07-16 LTS
2 回答

慕虎7371278
TA贡献1802条经验 获得超4个赞
我的理解是,通用方法/类/接口将被编译为单个类文件,其中类型参数被替换为最合适的下限
您的理解是正确的,但编译器旨在更智能地处理泛型。如果编译器的设计完全按照您所描述的方式设计,那么泛型的意义何在?我可以写一个方法Integer
来代替。不需要泛型,因为编译器只会替换我拥有的任何类型参数Integer
。
您已指定它T
必须是Integer
或 的子类Integer
。想想当T
是 的子类时的情况Integer
,下面的赋值仍然有效吗?不会的!
t = Integer.valueOf(2); // you are assigning an instance of a superclass to a subclass variable
您可能会争辩说Integer
不能有任何子类final
,但编译器并不是为了检查final
这种情况下类的性质而设计的。在这里用作Integer
界限可能意味着它reassign
根本不应该是通用的。
编译器做的另一件事是在必要时插入强制转换,但这与这个问题并不真正相关。

胡说叔叔
TA贡献1804条经验 获得超8个赞
它不起作用的原因是编译器无法证明它T实际上是T. 整数在这里是一个坏例子,因为它是最终的,没有人可以扩展它,但编译器不够智能,无法知道这一点并对其进行推理。
假设您有以下内容
class Foo{
}
class Bar extends Foo {
}
你像这样调用重新分配
reassign(new Bar());
允许重新分配的地方
<T extends Foo> T reassign(T t){
t = new Foo();
return t;
}
那么这相当于说
Bar b = new Foo()
这当然是无效的
添加回答
举报
0/150
提交
取消