簡體   English   中英

為什么Java中的bridge方法不能防止這種情況並引發異常?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM