zoukankan      html  css  js  c++  java
  • 类型通配符

    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的父类。
  • 相关阅读:
    tomcat调试模式出问题的解决方法
    文本输入 的 onfucus 和 onblur
    how to choose one of compenent and control
    C# Captcha 测试 firefox 和 IE
    谈谈对GridView控件DataKeyName属性的一点认识
    Response.Redirect和Server.Transfer的区别
    select 基本常用语法
    top、postop、scrolltop、scrollHeight、offsetHeight
    onchange 和 onpropertychange区别
    try catch 和if else 语句区别细说
  • 原文地址:https://www.cnblogs.com/dongyaotou/p/15662448.html
Copyright © 2011-2022 走看看