我以前從來沒有這樣做過,但昨天我真的想看看型別擦除會發生什么 - 很多書都給出了這樣的例子(這個是形式 OCP 11)
public class Crate<T> {
private T contents;
public Crate() {
}
public T emptyCrate() {
return this.contents;
}
public void packCrate(T contents) {
this.contents = contents;
}
public static void main(String[] args) {
Crate<String> stringCrate = new Crate();
stringCrate.packCrate("content");
String content = (String)stringCrate.emptyCrate();
}
}
據說編譯為:
public class Crate {
private Object contents;
public Object emptyCrate() {
return contents;
}
public void packCrate(Object contents) {
this.contents = contents;
}
public static void main(String[] args) {
Crate stringCrate = new Crate();
stringCrate.packCrate("content");
String content = (String)stringCrate.emptyCrate();
}
}
但它實際上編譯為:
public class Crate<T> {
private T contents;
public Crate() {
}
public T emptyCrate() {
return this.contents;
}
public void packCrate(T contents) {
this.contents = contents;
}
public static void main(String[] args) {
Crate<String> stringCrate = new Crate();
stringCrate.packCrate("content");
String content = (String)stringCrate.emptyCrate();
}
}
我在 IntelliJ 中使用 FernFlower 進行反編譯。基本上,唯一改變的是
String content = (String)stringCrate.emptyCrate();
所以我現在的問題是:這些書錯了,編譯器上是否有任何標記可以洗掉資訊,反編譯器是否太聰明了,我如何才能真正看到編譯器創建的代碼?
uj5u.com熱心網友回復:
這本書試圖說明的一點是,運行時不關心泛型型別引數。它表明這是通過在教學上“撒謊”給您的情況,即類檔案不包含任何泛型型別變數或引數,這是可以理解的,但也不是真的。
類檔案確實包含在欄位、方法和類宣告中使用的型別變數和泛型引數。你甚至可以通過反射得到它們!
// Both of these will print T
System.out.println(Crate.class.getTypeParameters()[0]);
System.out.println(Crate.class.getDeclaredField("contents").getGenericType());
只是運行時不關心例如您是否分配了不T屬于型別的欄位T。
另一方面,如果在編譯代碼時包含除錯資訊,則區域變數的泛型型別將保留在類檔案中 ( -g:vars)。這就是為什么您可以Crate<String>在類檔案中看到的原因。如果你這樣做了-g:none,它將顯示為:
Crate var1 = new Crate();
在 IntelliJ 中。請注意,變數的名稱也不見了:)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/362167.html
標籤:爪哇
上一篇:檢查玩家是否在移動
下一篇:如何在串列中收集串列
