Java中Set與Set<?>到底區別在哪?
- 2019 年 10 月 11 日
- 筆記
您可能知道,無界通配符 Set<?> 可以容納任何類型的元素,而原始類型Set也可以容納任何類型的元素。那它們之間有什麼區別呢?
1.關於Set<?>的兩個事實
關於Set<?>有兩個事實:
- Item 1:?代表任何類型。Set<?> 可以容納任何類型的元素。_
- Item 2:因為我們不知道?的類型,所以不能將任何元素放入Set<?>。
因此 Set<?> 可以容納任何類型的element(Item 1),但我們不能將任何元素放入其中(Item 2)。這兩個陳述是否彼此衝突?當然不是。以下兩個示例可以清楚地說明這一點:
Item 1表示以下情況:
//合法 程式碼 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。
Item 2是指以下非法情況:
//非法程式碼 public static void printSet(Set<?> s) { s.add(10);//this line is illegal for (Object o : s) { System.out.println(o); } }
因為我們不完全知道 <?> 的類型,所以除了null之外,我們無法添加其他任何內容。出於相同的原因,我們無法使用 Set<?> 初始化集合。以下是非法的:
//非法程式碼 Set<?> set = new HashSet<?>();
正是金九銀十跳槽季,為大家收集了2019年最新的面試資料,有文檔、有攻略、有影片。有需要的同學可以在公眾號【Java知己】,發送【面試】領取最新面試資料攻略!暗號【1024】千萬不要發,否則…..
2.Set 與 Set<?>
原始類型集和無界通配符集<?>有什麼區別?
此方法聲明很好:
public static void printSet(Set s) { s.add("2"); for (Object o : s) { System.out.println(o); } }
因為原始類型沒有限制。但是,這很容易破壞集合的不變性。
簡而言之,通配符類型是安全的,而原始類型則不是。我們不能將任何元素放入Set<?>中。
3.Set<?>什麼時候有用?
如果要使用泛型類型,但不知道或不在乎該參數的實際類型,則可以使用<?> 。它只能使用方法的參數。
例如:
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; }
參考:
1.布洛赫,約書亞。有效的java。Addison -Wesley Professional,2008年。
