繁体   English   中英

无法将有效常量(值)分配给通用类型变量

[英]Cannot assign valid constant(value) to a Generic Type variable

为什么以下不起作用?

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;
}

我的理解是泛型方法/类/接口将被编译为单个 class 文件,其中类型参数被替换为最合适的下限(在上述情况下为整数)。

Java 环境:java 11.0.4 2019-07-16 LTS

我的理解是泛型方法/类/接口将被编译为单个 class 文件,其中类型参数替换为最合适的下限

您的理解是正确的,但编译器旨在更智能地处理 generics。 如果编译器完全按照您描述的方式设计,那么 generics 有什么意义? 我可以只写一个采用Integer的方法。 不需要 generics,因为无论如何编译器只会Integer替换我拥有的任何类型参数。

您已指定T必须是IntegerInteger的子类。 想想当TInteger的子类时的情况,下面的赋值仍然有效吗? 它不会!

t = Integer.valueOf(2); // you are assigning an instance of a superclass to a subclass variable

您可能会争辩说Integer不能有任何子类,因为它是final ,但编译器并非旨在检查这种情况下类的final性。 在这里使用Integer作为界限可能意味着reassign根本不应该是通用的。


编译器做的另一件事是在必要时插入强制转换,但这与这个问题并不真正相关。

它不起作用的原因是编译器无法证明T实际上是而不是T的子类型。 Integer 在这里是一个不好的例子,因为它是最终的,没有人可以扩展它,但是编译器不够聪明,无法知道这一点并对其进行推理。

想象一下你有以下

 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()

这当然是无效的

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM