ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

类型通配符

2021-12-08 17:05:13  阅读:108  来源: 互联网

标签:name 通配符 Cat 类型 new public


1.什么是类型通配符

  • 类型通配符一般是使用"?"代替具体的类型实参。

  • 所以,类型通配符是类型实参,而不是类型形参。

小案例:

package com.genericity.demo2;

/**
 * 创建泛型类
 * @param <T>
 */
public class Box<T> {
    private T first;

    public T getFirst() {
        return first;
    }

    public void setFirst(T first) {
        this.first = first;
    }
}
 1 package com.genericity.demo2;
 2 
 3 public class MainClass {
 4     public static void main(String[] args) {
 5         //进行测试
 6         Box<Number> box1 = new Box<>();
 7         box1.setFirst(100);
 8         showBox(box1);//运行结果:100
 9 
10 //        Box<Integer> box2 = new Box<>();
11 //        box2.setFirst(200);
12 //        showBox(box2);//我们都知道Integer继承至Number,但是我的定义的方法是public static void showBox(Box<Number> box){ 他是不支持的,即使这样public static void showBox(Box<Integer> box){ 也是不行的。
13         //我们可以使用类型通配符的方式  public static void showBox(Box<?> box){
14 
15         Box<Integer> box2 = new Box<>();
16         box2.setFirst(200);
17         showBox(box2);//运行结果:200
18 
19 
20     }
21 //    public static void showBox(Box<Number> box){
22 //        Number first = box.getFirst();
23 //        System.out.println(first);
24 //    }
25 
26     /**
27      * 使用类型通配符的方式
28      *
29      * @param box
30      */
31     public static void showBox(Box<?> box) {
32         Object first = box.getFirst();
33         System.out.println(first);
34     }
35 
36     /**
37      * 这样也是不行的
38      * @param box
39      */
40 //    public static void showBox(Box<Integer> box){
41 //        Integer first = box.getFirst();
42 //        System.out.println(first);
43 //    }
44 }
View Code

2.类型通配符的上限(接上文)

  • 语法:类/接口

  • 要求该泛型的类型,只能是实参类型,或实参类型的子类类型。

    上面的代码我们看着是不是十分的不爽,既然是?通配符了,但是返回的还是Object类型的。

1 /**
2      * 使用类型通配符的方式
3      *
4      * @param box
5      */
6     public static void showBox(Box<?> box) {
7         Object first = box.getFirst();
8         System.out.println(first);
9     }
View Code

对上面的代码使用类型通配符的上限的方式进行改造

 1 package com.genericity.demo3;
 2 
 3 public class MainClass {
 4     public static void main(String[] args) {
 5         //进行测试
 6         Box<Number> box1 = new Box<>();
 7         box1.setFirst(100);
 8         showBox(box1);//运行结果:100
 9 
10         Box<Integer> box2 = new Box<>();
11         box2.setFirst(200);
12         showBox(box2);
13 
14     }
15 
16     /**
17      * 使用类型通配符的方式
18      * 使用类型通配符的上限,这样我们在传值的时候,就可以传Number类型或者是Number类型的子类
19      * @param box
20      */
21     public static void showBox(Box<? extends Number> box) {
22         Number first = box.getFirst();
23         System.out.println(first);
24     }
25 
26 }
View Code

小案例:

1 package com.genericity.demo3;
2 
3 public class Animal {
4 }
View Code
1 package com.genericity.demo3;
2 
3 public class Cat extends Animal {
4 }
View Code
1 package com.genericity.demo3;
2 
3 public class MiniCat extends Cat {
4 }
View Code
 1 package com.genericity.demo3;
 2 
 3 import java.util.ArrayList;
 4 
 5 /**
 6  * 类型通配符上限方式
 7  */
 8 public class Test {
 9     public static void main(String[] args) {
10         ArrayList<Animal> animals= new ArrayList<>();
11         ArrayList<Cat> cats= new ArrayList<>();
12         ArrayList<MiniCat> miniCats= new ArrayList<>();
13 
14 //        showAnimal(animals); Animal类不是Cat类型或者Cat类型的子类
15         showAnimal(cats);
16         showAnimal(miniCats);
17 
18         /**
19          * 源码:
20          * public boolean addAll(Collection<? extends E> c) {
21          *         Object[] a = c.toArray();
22          *         int numNew = a.length;
23          *         ensureCapacityInternal(size + numNew);  // Increments modCount
24          *         System.arraycopy(a, 0, elementData, size, numNew);
25          *         size += numNew;
26          *         return numNew != 0;
27          *     }
28          */
29 
30         cats.addAll(miniCats);//输入的时候提示:addAll(Collection<? extends Cat>
31     }
32 
33     /**
34      * 泛型上限通配符,传递的集合类型,只能是Cat或者Cat的子类类型
35      * @param list
36      */
37     public static void showAnimal(ArrayList<? extends Cat> list){
38         //注意:使用类型通配符上限的这种方式是不能添加元素的,因为你不能确定?号代表的是什类型,是Cat类还是MiniCat类,如果是MiniCat类的话,就会报错,所以是不行的。
39 //        list.add(new Animal());
40 //        list.add(new Cat());
41 //        list.add(new MiniCat());
42         for (int i = 0; i < list.size(); i++) {
43             Cat cat = list.get(i);
44             System.out.println(cat);
45         }
46     }
47 }
View Code

3.类型通配符的下限

语法:

类/接口

要求该泛型的类型,只能是实参类型,或实参类型的父类类型。

小案例:

 1 package com.genericity.demo3;
 2 
 3 import java.util.ArrayList;
 4 
 5 /**
 6  * 类型通配符下限方式
 7  */
 8 public class TestDown {
 9     public static void main(String[] args) {
10         ArrayList<Animal> animals= new ArrayList<>();
11         ArrayList<Cat> cats= new ArrayList<>();
12         ArrayList<MiniCat> miniCats= new ArrayList<>();
13 
14         showAnimal(animals);
15         showAnimal(cats);
16 //        showAnimal(miniCats) miniCats类不是Cat类型或者Cat类型的父类
17 
18     }
19 
20     /**
21      * 泛型下限通配符,传递的集合类型,只能是Cat或者Cat的子类类型
22      * @param list
23      */
24     public static void showAnimal(ArrayList<? super Cat> list){
25         //注意:使用类型通配符下限的这种方式是能添加元素的
26 //        list.add(new Animal()); Cat的父类元素是不能添加的,是能添加子类对象的
27         list.add(new Cat());
28         list.add(new MiniCat());
29         /**
30          * 注意:使用类型通配符下限的这种方式,返回值类型是Object类型,因为所有类的父类都是Object
31          */
32         for (int i = 0; i < list.size(); i++) {
33             Object object = list.get(i);
34             System.out.println(object);
35         }
36     }
37 }
View Code

小案例:通过对TreeSet的讲解,进一步加深对类型通配符上下限的理解

 1 package com.genericity.demo4;
 2 
 3 public class Animal {
 4     public String name;
 5 
 6     public Animal(String name) {
 7         this.name = name;
 8     }
 9 
10     @Override
11     public String toString() {
12         return "Animal{" +
13                 "name='" + name + '\'' +
14                 '}';
15     }
16 }
View Code
 1 package com.genericity.demo4;
 2 
 3 public class Cat extends Animal {
 4     public int age;
 5 
 6     public Cat(String name, int age) {
 7         super(name);
 8         this.age = age;
 9     }
10 
11     @Override
12     public String toString() {
13         return "Cat{" +
14                 "age=" + age +
15                 ", name='" + name + '\'' +
16                 '}';
17     }
18 }
View Code
 1 package com.genericity.demo4;
 2 
 3 public class MiniCat extends Cat {
 4     public int level;
 5 
 6     public MiniCat(String name, int age, int level) {
 7         super(name, age);
 8         this.level = level;
 9     }
10 
11     @Override
12     public String toString() {
13         return "MiniCat{" +
14                 "level=" + level +
15                 ", age=" + age +
16                 ", name='" + name + '\'' +
17                 '}';
18     }
19 }
View Code
 1 package com.genericity.demo4;
 2 
 3 import java.util.Comparator;
 4 import java.util.TreeSet;
 5 
 6 /**
 7  * 讲解TreeSet 类型上下限通配符的使用
 8  */
 9 public class Test {
10     public static void main(String[] args) {
11         /**
12          * 分别传入自己定义的不同的比较器Comparator1 Comparator2 Comparator3
13          */
14         TreeSet<Cat> treeSet=new TreeSet<>(new Comparator1());
15         treeSet.add(new Cat("jerry",20));
16         treeSet.add(new Cat("amy",22));
17         treeSet.add(new Cat("frank",35));
18         treeSet.add(new Cat("jim",15));
19         for (Cat cat : treeSet) {
20             System.out.println(cat);
21         }
22     }
23 }
24 
25 class Comparator1 implements Comparator<Animal>{
26 
27     @Override
28     public int compare(Animal o1, Animal o2) {
29         return o1.name.compareTo(o2.name);
30     }
31 }
32 class Comparator2 implements Comparator<Cat>{
33 
34     @Override
35     public int compare(Cat o1, Cat o2) {
36         return o1.age-o2.age;
37     }
38 }
39 class Comparator3 implements Comparator<MiniCat>{
40 
41     @Override
42     public int compare(MiniCat o1, MiniCat o2) {
43         return o1.level-o2.level;
44     }
45 }
View Code
使用Comparator1 运行结果:

Cat{age=22, name='amy'}
Cat{age=35, name='frank'}
Cat{age=20, name='jerry'}
Cat{age=15, name='jim'}   

由此可以看出是按照  a   f   je  ji 排列的

使用Comparator2 运行结果:

Cat{age=15, name='jim'}
Cat{age=20, name='jerry'}
Cat{age=22, name='amy'}
Cat{age=35, name='frank'}

由此可以看出是按照 10  20  22  35由小到大 排列的

使用Comparator3 会出现编译错误:

原因:(使用源码分析)
public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator));
}
由此可以看出:这里要传入的比较器必须得是Cat或者Cat的父类才行,而MiNiCat不是Cat的父类。

 

标签:name,通配符,Cat,类型,new,public
来源: https://www.cnblogs.com/dongyaotou/p/15662448.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有