java泛型上下限

た 入场券 2022-02-04 06:15 356阅读 0赞

前言:

  java的泛型上下限不是很好理解,尤其像我这种菜鸡。反反复复看了好几遍了…,真是…

一、简单的继承体系

  1. class Person{}
  2. class Student extends Person{}
  3. class Worker extends Person{}

二、泛型上限(extends 关键字)

  1. public static void upperBound(List<? extends Person> list, Person p){
  2. //正确,因为null没有类型信息
  3. list.add(null);
  4. //错误,因为list的参数类型可能是Person的子类
  5. list.add(p);①
  6. //成功获取
  7. if(list.size() > 0){
  8. Person pp = list.get(0);②
  9. }
  10. }

  ①处的错误在于list的参数类型是不确定的,其参数类型可能是 Person的子类,子类集合(List)不能添加父类的元素。测试如下:

  1. public static void testUpperBound(){
  2. ArrayList<Student> slist = new ArrayList<Student>();
  3. Person p = new Person();
  4. upperBound(slist, p);//无法添加成功
  5. }

  如何解决泛型上限添加问题,可以使用泛型方法,如下:

  1. public static <T extends Person> void upperBound2(List<T> list, T p){
  2. list.add(p);
  3. }
  4. public static void testUpperBound2(){
  5. ArrayList<Person> plist = new ArrayList<Person>();
  6. Person p = new Person();
  7. Student s = new Student();
  8. upperBound2(plist, p);
  9. upperBound2(plist, s);
  10. }

  也就是说,使用泛型上限add方法时,集合参数类型 和 元素参数类型 要一致,这样添加的时候才不会有矛盾。看一下eclipse中对upperBound2(plist, s);这个函数调用的提示,如下:

img_c85d2e1eab4d7beb48dc939589be308f.png

  可见,T类型最终会解析为 泛型的最上限类型,Student s相应的向上转型。

  接着说 ② 处,为什么能获取成功呢?泛型上限嘛,至少上限的类型是确定的,所有的上限类型的子类都可以进行向上转型,自然获取是不成问题了。

三、泛型的下限

  1. public static void lowerBound(List<? super Student> list){
  2. Person var = new Person();
  3. //错误,list的参数类型可能是 Student,这样就不能添加父类Person了,所以 变量var的类型 必须是 Student或者 Student的子类
  4. list.add(p);①
  5. //正确
  6. Student s = new Student();
  7. list.add(s);
  8. }
  9. public static void testlowerBound(){
  10. ArrayList<Person> list = new ArrayList<Person>();
  11. lowerBound(list);
  12. }

  ①处添加失败,告诉我们,泛型下限使用add方法添加元素时,元素的参数类型必须是 下限 或者 下限的子类型。否则会出现子类集合添加父类元素。

  1. public static void lowerBound2(List<? super Person> list){
  2. Person p = new Person();
  3. list.add(p);
  4. //获取,不能编译
  5. Person as = list.get(0);①
  6. }
  7. public static void testlowerBound2(){
  8. ArrayList<Person> list = new ArrayList<Person>();
  9. lowerBound2(list);
  10. }

  ①处获取失败了,我们看一下eclipse提示我们该怎么办?

img_5a6fea0fb658eb586f2bcbcbfa3d9ac1.png

  将 第二个方法 将”as”的类型更改为”Object” 和 泛型的下限 结合一下考虑一下,add(e)方法在正确添加后,都会成为Object对象,在使用get(index)方法时,会转换为

? super Person类型(可能是Person类型,也可能是Person的父类类型,甚至是Object),执行Person as = list.get(0),那么就有了 向下转型。java中无法保证向下转型是安全的。所以①处不能编译。

四、泛型上限最常见的一个应用

  1. List<Person> plist = new ArrayList<Person>();
  2. List<Student> slist = new ArrayList<Student>();
  3. plist.addAll(slist);

img_c9a7f161c1943dc3e3cb430ee868a386.png

五、泛型下限最常见的一个应用

  1. Set<Student> set = new TreeSet<Student>(new Comparator<Person>() {
  2. @Override
  3. public int compare(Person o1, Person o2) {
  4. return 0;
  5. }
  6. });

img_a6f15584b730f2785a4cc9b90907bb42.png

六、泛型上下限一个综合的例子

  注:个人瞎掰的…,就是将上面两个例子结合在一起!

  1. Set<Person> set = new TreeSet<Person>(new Comparator<Person>() {
  2. @Override
  3. public int compare(Person o1, Person o2) {
  4. return 0;
  5. }
  6. });
  7. List<Student> slist = new ArrayList<Student>();
  8. List<Worker> wlist = new ArrayList<Worker>();
  9. set.addAll(slist);
  10. set.addAll(wlist);

  接下来,研究一下泛型的擦除…

发表评论

表情:
评论列表 (有 0 条评论,356人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java下限

    前言:   java的泛型上下限不是很好理解,尤其像我这种菜鸡。反反复复看了好几遍了...,真是... 一、简单的继承体系 class Person{}