Java泛型中关于通配符的一些知识-小白笔记

在这里插入图片描述

泛型通配符

泛型在继承方面的体现

  虽然类A是类B的父类,但是G<A> 和G<B>二者不具备子父类关系,二者是并列关系。
 
  补充:类A是类B的父类,A<G> 是 B<G> 的父类

下面我举个例子:例子1:

@Test
    public void test1(){

        Object obj = null;
        String str = null;
        obj = str;//此时可以赋值

        Object[] arr1 = null;
        String[] arr2 = null;
        arr1 = arr2;//此时也可以赋值
        
         //但是下列这种情况编译不通过,因为不是Date与String不是子父类关系
//        Date date = new Date();
//        str = date;

这个例子可以看出:
子父类关系是可以相互赋值的,而并列关系却不能赋值,因为这Date与String没有关联关系,两个类是不同类型的。

所以我们可以拿泛型的例子:


		List<Object> list1 = null;
        List<String> list2 = new ArrayList<String>();
        //此时的list1和list2的类型不具有子父类关系
        //编译不通过
 //     list1 = list2;
 

例2:

	//print(list1);不通过
//	print(list2);不同过

 public void print(List<T> list){
        Iterator<T> iterator = list.iterator();
        while(iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj);

回到上面的例子,以上情况就不能使用同一个方法,需要大量的重载print的方法。如何解决上面的问题?总不能为了定义一个新的方法来处理List类型的类,这显然与java中的多台理念相违背。因此我们需要一个在逻辑上可以表示同时是List和List父类的引用类型。由此类型通配符应运而生。

那么,我们如何才能像例子1中的Str和obj一样赋值?而且使用print方法。此时我们就要使用:“通配符?"

@Test
    public void test3(){
        List<Object> list1 = null;
        List<String> list2 = null;
        
        List<?> list = null;//相当于桥梁

        list = list1;
        list = list2;
        
        //编译通过  //通过通配符后可以使用同一方法
//        print(list1);
//        print(list2);

        List<String> list3 = new ArrayList<>();
        list3.add("AA");
        list3.add("BB");
        list3.add("CC");
        list = list3;

        //添加(写入):对于List<?>就不能向其内部添加数据。
        //除了添加null之外。
//        list.add("DD");
//        list.add('?');

        list.add(null);

        //获取(读取):允许读取数据,读取的数据类型为Object。
        Object o = list.get(0);
        System.out.println(o);
        
  public void print(List<?> list){//通配符的方法
        Iterator<?> iterator = list.iterator();
        while(iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }

这个例子说明:通过通配符后,就可以使用方法print和相互赋值了。
此时 :
类Object是类Stirng的父类,List和List是没有关系的,二者共同的父类是:List<?>

2.有限的通配符<?>

通配符指定上限
上限extends :使用时指定的类型必须是继承某个类,或者实现某个接口,即 <=
通配符指定下限
下限super :使用时指定的类型不能小于操作的类
如下:看例子:
List<? extends Person1>
List<? super Person1>

class Person{
}

class Student extends Person{
}

   @Test
    public void test(){

        //只能Person与Person的子类使用
        List<? extends Person1> list1 = null;//(Person子类,Person]

        //只能Person与Person的父类使用
        List<? super Person1> list2 = null;//[Person,person父类)

        List<Student1> list3 = new ArrayList<Student1>();
        List<Person1> list4 = new ArrayList<Person1>();
        List<Object> list5 = new ArrayList<Object>();

        list1 = list3;
        list1 = list4;
//        list1 = list5;//Object是Person的父类。超过了界限

//        list2 = list3;//小于了Person的界限,必须是Person本身与Person父类使用
        list2 = list4;
        list2 = list5;

在读取数据方面:

//读取数据
        list1 = list4;//此时list1的类型是Person
        //可以使用Person与Object接收 因为Person,Object可以接收Person和Student的值
        Person1 person1 = list1.get(0);
        //返回的类型可能是Person 因为Student < Person所以 不能用Student来接收Person的值
//        Student s = list1.get(0);

        list2 = list4;
        //返回的类型可能是Person或Object的值,所以只能使用Object接收
        Object obj = list2.get(0);
        //返回的类型可能有Object的值,Person接收不了Object的值
//        Person1 p = list2.get(0);//不能用Person接收 Person < Object

在写入数据方面

 //写入数据
        //编译错误,
//        <? extends Person> ?不确定,要是放入Student有可能?比Student小,
//        list1.add(new Student1());
//        list1.add(new Person1());
//        list1.add(new Object());
//        <? super Person> ?不确定,?最起码可以是Person,那比Person更小的都可以
        list2.add(new Student1());
        list2.add(new Person1());
//        list2.add(new Object());//因为[Person - Object)那么要是?是Objcet更不满足要求

最后:小白是新手,写得不好请大佬勿喷。
在这里插入图片描述

发布了12 篇原创文章 · 获赞 39 · 访问量 648

猜你喜欢

转载自blog.csdn.net/weixin_46146269/article/details/104893680