您可能知道,無界通配符 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 3是指以下非法情況:**
//非法代碼
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<?>();
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年。
“不積跬步,無以至千里”,希望未來的你能:有夢為馬 隨處可棲!加油,少年!
關注公眾號:「Java 知己」,每天更新 Java 知識哦,期待你的到來!
發送「面試」,領取 BATJ 面試資料、面試視頻攻略。
發送「Group」,與 10 萬程序員一起進步。
發送「玩轉算法」,領取《玩轉算法》系列視頻教程。
千萬不要發送「1024」,否則......

