您可能知道,无界通配符 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」,否则......

Java中Set与Set<?>到底区别在哪?的更多相关文章

  1. Java中Set Map List 的区别

    java中set map list的区别: 都是集合接口 简要说明 set --其中的值不允许重复,无序的数据结构 list   --其中的值允许重复,因为其为有序的数据结构 map--成对的数据结构 ...

  2. 转:Java中abstract和interface的区别

    转自:Java中abstract和interface的区别 abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java ...

  3. 转:二十一、详细解析Java中抽象类和接口的区别

    转:二十一.详细解析Java中抽象类和接口的区别 http://blog.csdn.net/liujun13579/article/details/7737670 在Java语言中, abstract ...

  4. java中堆和堆栈的区别

    java中堆和堆栈的区别(一) 1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取 ...

  5. Java中Comparable和Comparator接口区别分析

    Java中Comparable和Comparator接口区别分析 来源:码农网 | 时间:2015-03-16 10:25:20 | 阅读数:8902 [导读] 本文要来详细分析一下Java中Comp ...

  6. Java中this与super的区别【6】

    若有不正之处,请多多谅解并欢迎批评指正,不甚感激.请尊重作者劳动成果: 本文原创作者:pipi-changing本文原创出处:http://www.cnblogs.com/pipi-changing/ ...

  7. Java中堆和栈的区别(转)

    栈与堆都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆.      Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new. ...

  8. Java中Long与long的区别(转)

    Java中Long与long的区别(转) [本文转载自:http://www.cnblogs.com/bluestorm/archive/2012/04/22/2464739.html] 转载请联系原 ...

  9. Java中ArrayList与LinkedList的区别

    Java中ArrayList与LinkedList的区别 一般大家都知道ArrayList和LinkedList的区别: 1. ArrayList的实现是基于数组,LinkedList的实现是基于双向 ...

随机推荐

  1. Linux中jar包启动和jar包后台运行

    Linux 运行jar包命令如下: 方式一: java -jar shareniu.jar 特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出 那如何让窗口不锁定? ...

  2. InnoDB On-Disk Structures(四)--Doublewrite Buffer (转载)

    转载.节选于 https://dev.mysql.com/doc/refman/8.0/en/innodb-doublewrite-buffer.html The doublewrite buffer ...

  3. zhy2_rehat6_mysql02 - 5.7主从搭建.txt

    1.0------------锁库: mysql>FLUSH TABLES WITH READ LOCK; 这个命令是全局读锁定,执行了命令之后所有库所有表都被锁定只读.一般都是用在数据库联机备 ...

  4. 如何在asm上定位数据块

    转自 https://blogs.oracle.com/database4cn/%e5%a6%82%e4%bd%95%e5%9c%a8asm%e4%b8%8a%e5%ae%9a%e4%bd%8d%e6 ...

  5. Centos8 配置静态IP

    安装centos 8之后,重启启动网络时,会出现以下报错 报错信息如下: Failed to start network.service: Unit network.service not found ...

  6. Javascript模块化开发3——Grunt之预处理

    一.grunt预处理简述 grunt的注册任务函数本身会对传入的参数和配置对象里的相关属性进行一定的预处理,方便任务函数进行操作. grunt的registerTask方法和registerMulti ...

  7. MySql-8.0.16-winx64 安装

    参考文章: https://www.cnblogs.com/lxlin/p/9635350.html https://www.cnblogs.com/xc1234/p/9050149.html MyS ...

  8. 并发容器之ConcurrentHashMap(JDK 1.8版本)

    1.ConcurrentHashmap简介 在使用HashMap时在多线程情况下扩容会出现CPU接近100%的情况,因为hashmap并不是线程安全的,通常我们可以使用在java体系中古老的hasht ...

  9. socket之线程来提高吞吐量

    线程demo: 线程: package com.company.s5; import java.io.InputStream; import java.io.InputStreamReader; im ...

  10. 关于如何获取项目所部署的本机IP和端口的问题

    关于如何获取项目所部署的本机IP和端口的问题 今天在写一个需求的时候碰到一个不常见的问题,在没有继承或者实现服务器提供的接口或者实现类的时候,比如说部署在tomacat上,某个类不去继承servelt ...