在定义泛型时,我们可以通过extends来限定泛型类型的上限,也可以通过super来限定下限,这两个限定字一般会和?等关键字搭配使用。

比如有这样的代码List<? super Father> dest,这里,super包含“高于”的意思,? Super Father就表示dest存放的对象应当“以Father为子类”;换句话说,在dest里,可以存放任何子类是Father类的对象。

再来看个extends的用法。比如有这样的代码,List<? extends Father> src,extends用来表示继承,这里的src可以存放以”Father”为父类的对象;也就是说,src可以存放任何Father对象的子类。

在实际的项目里,我们一般从List<? extends Father> src这类的集合里读元素,而从List<? super Father> dest这样的集合里写元素。通过下面的GenericExtends.java例子,再来了解extends,super和?的用法。

1    import java.util.ArrayList;
2    import java.util.List;
3    //定义一个空的父类和空的子类
4    class Father{ }
5    class Son extends Father{}
6    //这是个包含main方法的主类
7    public class GenericExtends {
8       //这个方法里,将把src里的对象复制到dest里
9       static void copy(List<? super Father> dest,
10                        List<? extends Father> src) {
11            for (int i=0; i<src.size(); i++)
12            {  dest.add(src.get(i));    }
13        }

在第9行copy方法的两个参数里,我们看到了两个包含extends和super泛型的参数。在方法体的for循环里,我们的做法符合刚才讲到的原则:从带extends泛型的集合里读,往带super泛型的集合里写。

14        public static void main(String[] args) {
15         Father f = new Father();
16            Son s = new Son();
17         //创建了一个带Father泛型的集合,并向其中放了一个元素
18            List<Father> srcFatherList = new ArrayList<Father>();
19            srcFatherList.add(f);
20            List<Father> destFatherList = new ArrayList<Father>();
21         //通过copy方法,把元素复制进了destFatherList里
22            copy(destFatherList,srcFatherList);
23         //这里的输出是1,说明copy方法成功地往destFatherList里写了元素
24            System.out.println(destFatherList.size());
25        }
26    }

在定义方法的参数时,我们可以用带extends和super的泛型来确保输入参数类型的准确性。除此之外,这两种泛型的用处不大,比如在main函数的第22行里,调用copy方法时,我们传入的参数都是List<Father>类型。

下面我们来展示些错误的用法:

错误用法一:用带问号的类型实例化集合对象。

1      List<?> list = new ArrayList<String>(); //正确
2     //List<?> list = new ArrayList<?>(); //错误

第1行里,虽然在等号的左边我们用到了问号,但在右边,我们确立了泛型类型是String,这个是正确的。与之相比,在等号的左边和右边我们都用了问号,这是错误的,因为编译器不知道list集合该采用哪种泛型类型。

错误用法二:向包含<? extends Father>泛型的集合里写。

1    List<? extends Father> list = new ArrayList<Father>();
2    //list.add(f); //error

第2行会报语法错,原因是编译器不知道这个基于Father的子类型究竟是什么;因为没法确定,为了保证类型安全,所以就不允许往里面加数据。

错误用法三:从包含<? super Father>泛型的集合里读。

1        List<? super Father> list1 = new ArrayList<Father>();
2        list.add(f); //正确
3        //list.get(0);//错误

第3行会报语法错,原因是编译器不知道该用哪种Father的父类来接收get的返回值;于是,同样为了保证类型安全,所以就不允许读。

从上述的第二和第三种错误的用法里,我们能感受到,extends和super这两种定义泛型的用法除了在定义方法参数之外,还真没其他合适的用途。

集合部分的面试点归纳:

对于初级程序员或者是刚完成升级的高级程序员来说,应该能“合理地”使用集合,这个要求看似不难,其实不然,搞懂了当然不难。

下面看些常见的面试题,并作相应的答疑。

1 ArrayList和LinkedList有什么差别?在哪种场景里应当用ArrayList(或LinkedList)?

大家如果学过数据结构,这个问题不难回答:前者是基于数组,数组比较擅长索引查找,但不擅长被频繁地插入或删除;后者是基于链表,它擅长被频繁地插入或删除,如果对其频繁地进行索引查找,就会影响性能。

2 ArrayList和Vector有什么差别?

我们知道,ArrayList是线程不安全的,而且会以大概50%的规模进行动态扩容;而Vector是线程安全的,它会以100%的规模进行动态扩容。所以在单线程环境下,出于性能和内存使用量这两方面的考虑,建议使用ArrayList。

3 我们知道,Set里不允许插入重复的元素。对于HashSet和TreeSet,如果我们要插入自定义的类,我们该往自定义的类里加入什么方法来保证“不重复”?

对于HashSet,它是基于Hash表的,我们需要重写其中的hashCode和equals方法;对于TreeSet,我们需要重写compareTo方法(当然还得实现Compareable接口)。

在大多数场景下,我们是会放入自定义类型,而不是简单数据类型。如果候选人不知道怎么回答,那么我就可以认定他只是“简单地用到了集合”,而不是“对集合有深入的了解”。

4 在使用迭代器遍历集合对象时,我们能不能边访问边修改?如果这样做,会有什么问题?

第一,会报异常,因为使用迭代器时不能边访问边修改;第二,这种异常其实是种保护机制,因为边遍历边修改会增加出错的机会;第三,如果确实需要这样做,可以使用CopyOnWriteArrayList之类的集合,或者干脆别通过迭代器来访问集合对象。

5 在使用HashMap时,你有没有重写hashCode和equals方法,如果不重写,会有什么问题?如果候选人对此一脸雾水,那么我会给点提示:如果我们要在HashMap的Key部分放入自定义的类,而不是基本数据结构,那么我们该在这个自定义的类里重写什么方法?

如果大家被问到这个问题,可以好好利用这个机会来展示你对此的深入了解。

要点1,HashMap是基于hash表这个数据结构来实现的,所以其中的get或containsKey的效率相当高(接近于1)。

要点2,描述一下Hash表的数据结构,重点说说如何通过hash算法把待存入的数据和存储位置绑定到一起了,同时还可以说出HashMap表里是通过链地址法来解决冲突。

要点3,hashCode方法其实是对应hash表里的hash算法,由此我们可以计算出待存储元素的存放位置。如果我们不重写,将会用到Object里的hashCode方法,它是返回该对象的内存地址;而如果我们不重写equals方法,那么在冲突的情况下,就无法定位到具体的对象了。总之,如果不重写hashCode和equals方法,在调用containsKey和get方法时,就无法得到“看上去一致”的对象了。

如果面试官(也包括笔者)看到应试者能清晰地说出上述的意思,就认为此人对技术细节非常了解,就有可能减少集合部分(或者乃至Java Core部分)的面试题。如果大家也是这样并在回答其它问题时不犯原则性的错误,那么也可能得到“对技术了解比较透彻”之类的好评。

6 Collections和Collection有什么差别?

Collections 是一个集合的一个类,其中包含有一些和集合操作相关的静态多态方法。Jave集合里则有另外一个和它非常相似的接口Collection(不带s),它是线性表类集合的父接口,List和Set等接口都是通过实现这个接口来实现的。

7 你有没有用过T,?, super和extends这种泛型?

说实在的,上述泛型在实际的项目里用得还真不多,你如果说没用过,面试官也不会难为你。不过大家可以结合3.5.1部分的知识点,向面试官说明你是怎么把泛型作用到类和方法上,也可以结合上文描述的copy方法向面试官说明? extends和? super的用法,如此面试官就会认为你对集合部分的知识掌握得很透彻。

转载于:https://www.cnblogs.com/JavaArchitect/p/8116240.html

泛型的继承和通配符,同时归纳集合部分的面试点相关推荐

  1. java:泛型(自定义泛型类、自定义泛型接口、泛型的继承和通配符说明)

    目录 一.泛型的介绍 二.泛型的语法 2.1 泛型的声明 2.2 泛型的实例化 2.3 泛型使用举例 2.3 泛型使用的注意事项和细节 2.4 泛型课堂练习题 2.5 自定义泛型类 2.6 自定义泛型 ...

  2. Java泛型(1)--集合使用泛型Generic、自定义泛型、泛型在继承上的体现、通配符的使用

    文章目录 泛型的概念 集合中使用泛型 自定义泛型结构 泛型在继承上的体现 通配符的使用 泛型的概念 集合容器类在设计阶段/声明阶段不能确定这个容器实际存的是什么类型的对象,所以在JDK1.5之前只能把 ...

  3. 泛型学习笔记:泛型使用的注意点、泛型在继承方面的体现、自定义泛型结构、泛型应用举例、通配符

    泛型学习笔记 集合是为了解决数组某些存储限制的特点出现的,但是数组有一个优点就是存放的数据的类型是确定的,但是集合容器在声明阶段存入的对象是什么类型是不确定的,所以在JDK1.5之前只能把元素的类型设 ...

  4. 泛型与继承的关系,通配符

    1 若类A是类B的子类,那么List<A>就不是List<B>的子接口 2 通配符:List[A],List[B]...都是List<?>的子类 extends A ...

  5. java 上界和下界,Java 泛型之上界下界通配符

    Java 泛型之上界下界通配符 Java教程是为JDK 8编写的.本页描述的示例和实践没有利用后续版本中引入的改进. 通配符和子类型 如 泛型,继承和子类型中所述,泛型类或接口仅仅因为它们的类型之间存 ...

  6. java泛型笔记2--上界通配符

    擦除特性 虚拟机没有泛型类型对象.无论何时,定义一个泛型类型,都会自动提供一个相应的原始类型.这个原始类型的名字就是去掉类型参数后的泛型类型名.类型变量会被擦除,并替换成其限定类型,对于无限定的变量, ...

  7. Java泛型解析(02):通配符限定

    Java泛型解析(02):通配符限定      考虑一个这种场景.计算数组中的最大元素. [code01] public class ArrayUtil {public static <T> ...

  8. 高中数学知识点总结汇总归纳:集合及其运算

    针对高中数学,不要盲目复习和做题,在学习中,我们应该掌握高中数学都有哪些知识点,通过做题发现出自己哪些知识点不足,这样才能快速提分.肖老师分享关于高中数学知识点总结汇总归纳:集合及其运算. 一.集 合 ...

  9. -1-3 java集合框架基础 java集合体系结构 Collection 常用java集合框架 如何选择集合 迭代器 泛型 通配符概念 Properties 集合 迭代器...

    集合又称之为容器存储对象的一种方式 •数组虽然也可以存储对象,但长度是固定的:显然需要可变长度的容器 集合和数组的区别?                 A:长度区别                  ...

  10. 泛型在继承方面的体现与通配符

    List<String>与List<Object>,并不具备父子类关系 List<Object>与ArrayList<Object> 存在父子类关系 通 ...

最新文章

  1. arcgis将小于0的数值设置成0.01
  2. 扫掠两条引导线_《神都夜行录》周年庆点燃线上线下,解读国风二次元IP的成长之路...
  3. 安全强化linux-SELinux
  4. Hibernate自动事务揪出的编码不规范
  5. SkinSharp用法
  6. 软件测试:做一些简单工作经历总结,自己想到那算那吧
  7. Effective C# 学习笔记 (一)
  8. LabVIEW编程LabVIEW开发Memmert oven温箱例程与相关资料
  9. 电子通信协议之CAN总线协议篇
  10. 主机安全扫描入门-用Java封装Nmap
  11. CSS border 属性
  12. C#微信、支付宝扫码支付源码
  13. 北京专精特新企业申报攻略
  14. 业务流程图怎么画?一篇文章看懂
  15. matlab读取wav文件
  16. 指数的增长和衰退问题
  17. 【RCNN】论文翻译-用于精确物体定位和语义分割的丰富特征层次结构
  18. css选择器优先级和photoshop快捷键以及100度享乐网框架
  19. Desktop Central 应用规范报告—如何利用BYOD(一)
  20. python爬虫解析库(Xpath、beautiful soup、Jsonpath)

热门文章

  1. vmware中nat模式上网
  2. SSIS包的组建之连接管理器
  3. 需求不容易确定的项目不要接
  4. 【LeetCode】【字符串】题号:*151. 翻转字符串里的单词
  5. PHP数据库统计时间戳按天分组输出数据
  6. 实习踩坑之路:实习以来获得的踩坑经验、一些提升开发效率的方法或者常用技巧
  7. Apache Flink®生态所面临的机遇与挑战
  8. stm32for循环几个机械周期_带你了解包装机械设备的可调度性分析
  9. php判断平板,一种 PHP 判断设备是否是手机/平板的方法
  10. python 批量gif转tif_使用Python 批量转移*.tif和*.mov文件