当前位置: 首页 > article >正文

泛型(2)

泛型(2) 

1、泛型在继承上的体现

如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G并不是G的子类型!

比如:String是Object的子类,但是List并不是List的子类。

class A <T> extends superA<String>{......}

只有泛型类相同时,父类与子类之间才能体现继承关系。

例如:父类SuperA<String>与子类A<String>之间存在继承关系,类A的实例对象可以被SuperA引用体现多态性;但SuperB<Object>与B<String>之间没有继承关系。

2、通配符的使用

当我们声明一个变量/形参时,这个变量/形参的类型是一个泛型类或泛型接口,例如:Comparator类型,但是我们仍然无法确定这个泛型类或泛型接口的类型变量的具体类型,此时我们考虑使用类型通配符 ? 。

1 通配符的理解

使用类型通配符:?

比如:List<?>Map<?,?>

 List<?>List<String>List<Object>等各种泛型List的父类

2 通配符的读与写

写操作:

将任意元素加入到其中不是类型安全的:

Collection<?> c = new ArrayList<String>();

c.add(new Object()); // 编译时错误

因为我们不知道c的元素类型,我们不能向其中添加对象。add方法有类型参数E作为集合的元素类型。我们传给add的任何参数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我们无法传任何东西进去。

唯一可以插入的元素是null,因为它是所有引用类型的默认值。

读操作:

另一方面,读取List<?>的对象list中的元素时,永远是安全的,因为不管 list 的真实类型是什么,它包含的都是Object。

@Test
public void test1(){
    List<?>list = null;//通配符‘?’不确定类型
    List<String> list1 =Arrays.asList(new String[]{"Qum","Dit","TuSu"});
    list = list1;
    Object obj = list.get(0);//get得到Object的接收值
    System.out.println(obj);//可以读取,不能写入
}

总结:使用通配符的集合,可读不可写。其他泛型类型的集合可以赋值给使用通配符的集合。

@Test
public void test4(){
    List<?>list = new ArrayList<>();
    List <String> list1 = null;
    List <Integer>list2 = null;
    
    list = list1;//使用通配符作为泛型类型可以传入任意泛型类型的集合元素。
    list = list2;
    //list1 = list2;编译时错误,泛型类型不同不能传入集合元素。
}

3 使用注意点

注意点1:编译错误:不能用在泛型方法声明,返回值类型前面<>不能使用?

public static <?> void test(ArrayList<?> list){
}

注意点2:编译错误:不能用在泛型类的声明

class GenericTypeClass<?>{
}

注意点3:编译错误:不能用在创建对象上,右边属于创建集合对象

ArrayList<?> list2 = new ArrayList<?>();

4 有限制的通配符

  • <?>
    • 允许所有泛型的引用调用
  • 通配符指定上限:<? extends 类/接口 >
    • 使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
@Test
public void test2(){
    List<? extends Person> list = null;
    List<Object> list1 = null;
    List<Object> list2 = null;
    List<Person> list3 = null;
    List<Student> list4 = null;

    //list = list2;
    list = list3;//extend,继承于。 Person、Person的子类可以传入
    list = list4;
}
  • 无法写入数据,除了null
  • 通配符指定下限:<? super 类/接口 >
    • 使用时指定的类型必须是操作的类或接口,或者是操作的类的父类或接口的父接口,即>=
@Test
public void test3(){
    List<? super Person> list = null;
    List<Object> list1 = null;
    List<Object> list2 = null;
    List<Person> list3 = null;
    List<Student> list4 = null;

    list = list2;
    list = list3;//super,写入父类, Person或者其父类可以传入
    //list = list4;
}
  • 可以写入Person及其子类的数据。
  • 说明:
  1.  extends Number>     //(无穷小 , Number]
    //只允许泛型为Number及Number子类的引用调用

    <? super Number>      //[Number , 无穷大)
    //只允许泛型为Number及Number父类的引用调用

    <? extends Comparable>
    //只允许泛型为实现Comparable接口的实现类的引用调用


http://www.kler.cn/a/448318.html

相关文章:

  • Ubuntu vi(vim)编辑器配置一键补全main函数
  • Java实现贪吃蛇游戏
  • 算法学习(十六)—— 综合练习
  • VMware安装Ubuntu 16.04以及安装好后初步使用配置!
  • List深拷贝后,数据还是被串改
  • python 曲线拟合,曲线拟合交点
  • 开源!自制一个桌面宠物(STM32CUBEMX HAL库 PWM波 小项目)
  • 在 CUDA C/C++ 中使用共享內存
  • 路径规划之启发式算法之二十一:禁忌搜索算法(Tabu Search,TS)
  • Linux 端口操作
  • 【游戏设计原理】21 - 解谜游戏的设计
  • 【Mac】安装 PaddleOCR
  • springboot java ffmpeg 视频压缩、提取视频帧图片、获取视频分辨率
  • IntelliJ IDEA Docker集成
  • 适用于.net的操作excel的库
  • vsCode怎么使用vue指令快捷生成代码
  • stm32实现出厂设置和恢复出厂设置
  • python --机器学习(KNN相关)
  • 算法之物品移动
  • 鸿蒙元服务从0到上架【第二篇】
  • HarmonyOS NEXT 技术实践-实现音乐服务卡片
  • 简单介绍一下缓慢渐变维
  • java篇-maven配置阿里云仓库(图文详解)
  • sass、scss、less、的区别
  • 文献阅读+ARIMA模型学习
  • Fluss 写入数据湖实战