Java泛型通配符的使用

通配符的使用

   通配符:?

   类A是类B的父类,G<A>和G<B>是没有关系的,二者共同的父类是:G<?>
 /*

     */

    @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之外。 因为类的默认值都为null
//        list.add("DD");
//        list.add('?');

        list.add(null);

        //获取(读取):允许读取数据,读取的数据类型为Object。
        //我们可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个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);
        }
    }
=====================================================================


有限制条件的通配符的使用

    ? extends A:
            G<? extends A> 可以作为G<A>和G<B>的父类,其中B是A的子类

    ? super A:
            G<? super A> 可以作为G<A>和G<B>的父类,其中B是A的父类
看下面的代码(64-87行)理解这两句话:

    /*
    3.
     */
    @Test
    public void test4(){
		       //上限Person
        List<? extends Person> list1 = null;
        List<? super Person> list2 = null;//下限是Person

        List<Student> list3 = new ArrayList<Student>();
        List<Person> list4 = new ArrayList<Person>();
        List<Object> list5 = new ArrayList<Object>();
    
	//list1可以作为list3和list4的父类 ,其中list3是list4的子类。
    //extends可以看成 <= ; 在此代码中 <=Person 的类都可以赋值给list1。
        list1 = list3;
        list1 = list4;
//        list1 = list5; 编译不通过;因为Object > Person
    

**相反的,super可以看成 >=;在下面代码中,>=Person的类都可以赋值给list2.**
-----
    
//        list2 = list3; 编译不通过,因为list3(Student) < Person
        list2 = list4;
        list2 = list5;
    

  • //通过对上面代码的理解:应用场景 <? extends Comparable> // 只允许泛型为实现Comparable接口的实现类的引用调用
---------------------
 //读取数据:
 list1 = list3;
 Person p = list1.get(0); // List<? extends Person> 最大就是Person 要覆盖所有可能。
 //Student s = list1.get(0);
//编译不通过,list1.get(0)的值可能是Persn也可能是Student类, 如果返回的值是Person类,用Student去接收会出错的。
//要用最大的类型person(上限)接收类型
//子类可以赋值给父类,反过来不行
    
        list2 = list4;
        Object obj = list2.get(0);
        编译不通过 因为list2下限是Person ,可能有比person大的类过来,怎么能用person接收呢?类似上个说明。
//        Person obj = list2.get(0);

===========================================================
        //写入数据:
        //编译不通过
//        list1.add(new Student()); 
   /* Student虽然是Person的子类,但是<? extends Person> 代表 <= Person(没有下限,只有上限是Person。) 还有比Student更小的类,
   父类不可以赋值给子类*/
当你将一个变量声明为List<? extends Person>时,它表示一个未知类型的列表,该类型是Person的子类型或扩展类型。
它可以是StudentTeacherPerson的任何其他子类。

然而,编译器无法在运行时确定list1可以持有的具体Person子类型。
它可能是Student或任何其他子类,因此向这样的列表中添加元素是不安全的。
编译器会阻止你向列表中添加元素,因为无法保证被添加的元素与未知子类型兼容。

如果你想向列表中添加元素,应该将其声明为List<Person>,而不是List<? extends Person>。这样,
列表可以保存任何Person类型或其子类的对象,包括Student,你就可以将Student对象添加到列表中而不会出现编译错误。

        //编译通过 因为list2下限是Person 不能添加比Person大的类了。因为通配符(?)可能是比Person大的。
        list2.add(new Person());
        list2.add(new Student());//Student比Person还小 也可以添加。
    }

}

===========
## 注意点
============
~~~java
//注意点1:
public static <?> voidtest(ArrayList<?> list){
    //编译错误:不能用在泛型方法声明上,返回值类型前面<>不能使用?
}
//注意点2:
class GenericTypeClass<?>{
    //编译错误:不能用在泛型类的声明上
}
//注意点3:
ArrayList<?> list2 = new ArrayList<?>();
//编译错误:不能用在创建对象上;右边属于创建集合对象

 List<?> list = null;//这种是可以的。
 
通配符可以用在一般方法的参数上和对象的声明上。
~~~

## 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值