簡體   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