[英]why aren't the bridge methods in Java preventing this and throwing an Exception?
為什么下面的泛型代碼在運行時不引發異常?
public static void main(String[] args) {
((List)new ListString()).add(3);
}
static class ListString extends ArrayList<String>{
}
我知道這不是應該使用泛型的方式,但是我認為通過添加以下方法會拋出ClassCastException.
方法是橋接方法 ClassCastException.
public boolean add(Object o){
return add((E)o);
}
注意:如果我按照以下內容修改ListString類,則確實會引發ClassCastException:
static class ListString extends ArrayList<String>{
@Override
public boolean add(String o){
return super.add(o);
}
}
除非您實際編寫方法,否則不會創建網橋(綜合方法),就像您在后續測試中所做的那樣,您在代碼中放置了public boolean add(String o){return super.add(o);}
。
當您在StringList
類型的表達式上調用.get(someInt)
時,編譯器可以看到您的StringList
類型,即使它是ArrayList<String>
的子類型,也沒有任何帶有簽名String get(int)
。它。 因此,它Object get()
在字節碼中生成對Object get()
方法的調用,並(如果需要)對類型轉換進行調用,並且在Java方面,它的行為就像StringList
上的get方法返回String一樣。 即使在字節碼級別也沒有。
如果隨后出現String get(int)
方法String get(int)
例如,通過子類化StringList
或通過編輯源代碼並僅重新編譯該文件),則僅會生成bridge方法。 因為java是動態調度,所以始終使用該橋。 橋強制轉換並調用(或調用並強制轉換,取決於該橋是覆蓋返回類型的詭計還是參數詭計)。
您可以使用javap -v
驗證所有這些:我強烈建議所有發現這一點有趣並且想准確了解其工作原理的人,在探索兩者之間的輸出差異時會有些有趣:
import java.util.*;
public class Test extends ArrayList<String> {
public static void main(String[] args) {
List raw = new Test();
raw.add(3);
}
}
和這個:
import java.util.*;
public class Test extends ArrayList<String> {
public static void main(String[] args) {
List raw = new Test();
raw.add(3);
}
public boolean add(String o) {
return super.add(o);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.