簡體   English   中英

泛型和數組的不同Java行為

[英]Different Java behavior for Generics and Arrays

為什么Java允許將不一致的類型輸入到通用對象引用中而不是數組中?

例如:

初始化數組時:

int[] a = {1, 2, 3};

而且,如果我輸入:

int[] a = {1, 2, "3"}; //Error for incompatible types

對於仿制葯,

import java.util.ArrayList;

public class Test {
    private static ArrayList tricky(ArrayList list) {
        list.add(12345);
        return list;
    }
    public static void main(String[] args) {
        int i = 0;
        ArrayList<String> list = new ArrayList<>();
        list.add("String is King");
        Test.tricky(list);
    }
}

上面的代碼將使您可以在list對象中添加任何Type ,在某些情況下會導致運行時異常。

為什么會有這種行為? 請給一個適當的解釋。

該方法的參數沒有泛型,因此允許所有類。 您可以在Google上輸入“類型擦除”以獲取更多信息。

如果將泛型添加到方法中,則會出現編譯器錯誤:

private static ArrayList<String> tricky(ArrayList<String> list) { // ...

順便說一句,您不需要返回列表,因為您修改了同一實例。

原因如下:

之所以無法為數組編譯它,是因為存在運行時異常(ArrayStoreException),它將阻止您將錯誤類型的對象放入數組中。 如果將Dog數組發送到采用Animal數組的方法中,並且僅將Dogs(當然包括Dog子類型)添加到Animal現在引用的數組中,就沒有問題。 但是,如果您確實嘗試將Cat添加到實際上是Dog數組的對象中,則會出現異常。 通用方法(考試目標6.3和6.4)615616第7章:通用方法和集合

但是由於類型擦除,泛型沒有等效的例外! 換句話說,在運行時JVM知道數組的類型,但是不知道集合的類型。 所有通用類型信息在編譯過程中都會被刪除,因此,當它到達JVM時,根本無法識別將Cat放入ArrayList的災難,反之亦然(這就像您遇到的問題一樣)您使用傳統的非類型安全代碼)

禮貌:Kathy Sierra和Bert Bates撰寫的SCJP學習指南

當您聲明ArrayList就像ArrayList list = ...您不會聲明列表將包含的對象類型。 默認情況下,由於每種類型都有Object作為超類,因此它是ArrayList<Object> 為了好的做法,應該聲明ArrayList<SomeType>的類型,從而避免添加不一致的元素(根據類型)

由於尚未定義列表的通用類型,因此默認為List<Object> ,它接受擴展Object

通過自動裝箱,將原始int轉換為Integer ,當將Object添加到列表中時,該Integer擴展了Object

您的數組僅允許使用int ,因此不允許使用String

這是因為在方法參數中沒有為ArrayList指定特定類型,因此默認情況下它可以接受所有類型的對象。

import java.util.ArrayList;

public class Test {

//Specify which type of objects you want to store in Arraylist
    private static ArrayList tricky(ArrayList<String> list) {
        list.add(12345);   //This will give compile time error now
        return list;
    }
    public static void main(String[] args) {
        int i = 0;
        ArrayList<String> list = new ArrayList();
        list.add("String is King");
        Test.tricky(list);
    }
}

當您使用tricky方法將數據插入到ArrayList集合中時,它與指定的類型(即String不匹配,但是仍然兼容,因為泛型與舊的舊版代碼兼容。

如果不是這個原因,即如果它與數組的方式相同,那么所有Java之前的通用代碼都將被破壞,所有代碼都必須被重寫。

記住泛型的一件事,所有type-specifications都是編譯時限制的 ,因此,當您使用tricky方法在list引用中插入數據時,編譯器將其視為一個列表,除原語外,其他任何內容都可以添加。

僅當您編寫以下內容時:

...
public class Test {
    private static ArrayList tricky(ArrayList<String> list) {
        list.add(12345); //Error, couldn't add Integer to String
        return list;
    }
...
}

我已經為此寫了一篇文檔化的文章,請閱讀此處

暫無
暫無

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

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