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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值