Set vs. Set

翻譯自: Set vs. Set<?>

你可能知道一個無界的通配符Set <?>可以容納任何類型的元素,而一個原始類型Set也可以容納任何類型的元素。 但是他們有什麼區別呢?

1.Set<?>的兩個事實

(1)由於問號? 代表任何類型,所以 Set <?>能夠容納任何類型的元素;

(2)因爲我們不知道?的類型,所以我們不能把任何元素放入Set <?>中

所以一個Set <?>可以容納任何類型的元素(Item 1),但是我們不能放入任何元素(Item 2)。 這兩個說法是不是就相互衝突了? 當然,他們並不衝突。 這可以通過以下兩個例子清楚地說明:

第一個例子:

//Legal Code
public static void main(String[] args) {
    HashSet<Integer> s1 = new HashSet<Integer>(Arrays.asList(1, 2, 3));
    printSet(s1);

    HashSet<String> s2 = new HashSet<String>(Arrays.asList("a", "b", "c"));
    printSet(s2);
}

public static void printSet(Set<?> s) {
    for (Object o : s) {
        System.out.println(o);
    }
}

由於Set <?>可以容納任何類型的元素,我們只需在循環中使用Object(因爲Object是所有類的父類)。

第二種不合法的情況:

//Illegal Code
public static void printSet(Set<?> s) {
    s.add(10);//this line is illegal 
    for (Object o : s) {
        System.out.println(o);
    }
}

因爲我們完全不知道 ? 的類型,除了null之外,我們不能添加任何東西。 出於同樣的原因,我們不能用Set <?>初始化一個集合。 下面的這個操作是非法的:

//Illegal Code
Set<?> set = new HashSet<?>();  // compile error:Cannot instantiate the type HashSet<?>

2. Set vs. Set<?>

原始類型Set和無界通配符Set <?>有什麼區別?這個方法聲明得很好:

public static void printSet(Set s) {
    s.add("2");
    for (Object o : s) {
        System.out.println(o);
    }
}

因爲原始類型沒有添加限制。 但是,這很容易破壞集合的不變性,簡單的說,通配符類型是安全的,原始類型不是。 我們不能把任何元素放入Set <?>中。

3.Set<?>在什麼時候用?

當你想使用一個泛型類型,但是你不知道或不關心參數是什麼類型時,你可以使用<?> (參考:Bloch, Joshua. Effective java. Addison-Wesley Professional, 2008.), 它只能用作方法的參數。

例如:

public static void main(String[] args) {
    HashSet<Integer> s1 = new HashSet<Integer>(Arrays.asList(1,2,3));
    HashSet<Integer> s2 = new HashSet<Integer>(Arrays.asList(4,2,3));

    System.out.println(getUnion(s1, s2));
}

public static int getUnion(Set<?> s1, Set<?> s2){
    int count = s1.size();
    for(Object o : s2){
        if(!s1.contains(o)){
            count++;
        }
    }
    return count;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章