簡體   English   中英

為什么Java的類型擦除不會打破這個?

[英]Why does Java's type erasure not break this?

public class Test {
    public static class Nested<T> {
        public T val;
        Nested(T val) { this.val = val; }
    }
    public static void main(String[] args) {
        Nested<Integer> a = new Nested<Integer>(5);
        Nested<Integer> b = new Nested<Integer>(2);
        Integer diff = a.val - b.val;
    }
}

上面的代碼工作正常。 但是,如果我向嵌套添加一個方法:

T diff(Nested<T> other) { return this.val - other.val; }

我收到編譯錯誤:

operator - cannot be applied to T,T

這對我來說很有意義。 T的類型在運行時被擦除,因此Java不能應用僅為某些類(如Integer)定義的運算符。 但為什么a.val - b.val有效呢?

編輯:

很多好的答案。 感謝大家。 如果我理解正確的話,它的要點是編譯器可以在a.val - b.val向Integer添加強制轉換,因為它知道ab被實例化為Nested <Integer > 但是,由於this.val - other.val發生在泛型函數定義的主體內部(其中T仍然可以是任何東西),編譯器無法添加使“ - ”工作所必需的強制轉換。 這導致了一個更有趣的問題,即,如果Java編譯器能夠內聯,那么像diff這樣的泛型函數是否可以工作?

兩者之間的區別在於您是在通用方法中還是在其外部。

你得到的絕對正確的是,在方法T內部不知道是一個Integer ,所以運算符減去-不能應用。 但是,當您在main() ,在泛型方法之外時,編譯器知道您已使用Integer實例化Nested ,因此它非常清楚如何應用運算符。 盡管通用的實施,消除產生的代碼類型Nested<T>編譯器不會想到ab來講Nested<T>它有足夠的知識來插入合適的演員,拆箱結果,並申請減號-運營商。

您將收到編譯時錯誤,而不是運行時錯誤。

public static void main(String[] args) {
    Nested<Integer> a = new Nested<Integer>(5);
    Nested<Integer> b = new Nested<Integer>(2);
    Integer diff = a.val - b.val;
}

在這里,編譯器知道兩個T都是Integer 您剛剛聲明了<Integer>

T diff(Nested<T> other) { return this.val - other.val; }

在這里,編譯器不確定T 它可能是任何東西。 並且,僅限數字運算符-不允許任何內容。

a.val - b.val工作原理是因為它是由編譯器驗證的,而不是在運行時驗證的。 編譯器“看到”你正在使用<Integer>並且它編譯並運行Ok,在運行時即使擦除也沒有問題,因為編譯器已經驗證了這一點。

因為方法調用是在運行時,並且在編譯時檢查a.val - b.val

  • 在第一種情況下,編譯器知道類型是Integer並且-允許整數操作。
  • 在第二種情況下,編譯器事先不知道T的類型,因此不確定-操作是否有效。 因此編譯錯誤。

考慮我們將方法用作diff(Nested<Book> other)因此無法從其他書中減去書籍。

因為代碼不在嵌套中,所以類型是已知的。 編譯器可以清楚地看到a.val - b.val是一個Integer減去整數,可以自動裝箱。 編譯器基本上將其重寫為

Integer diff = Integer.valueOf(((Integer) a.val).intValue() - ((Integer) b.val).intValue())

.intValue和.valueOf調用來自自動裝箱和自動拆箱。

類型轉換對於編譯器來說是安全的,因為您使用了參數化類型Nested。

確實,從技術上講,a 可能是其他東西,比如Calendar對象,因為類型在運行時是未知的。 但是如果你使用泛型,編譯器會相信你沒有做任何愚蠢的事情來規避它。 因此,如果a.val或b.val不是Integers,則會在運行時拋出ClassCastException。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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