首页 > 编程语言 >Java 泛型

Java 泛型

时间:2023-06-23 10:22:18浏览次数:109  
标签:Java 子类 类型 擦除 协变 泛型

泛型 Genrics

Java 泛型是在jdk5引入的新特性。它指定了接收参数的类型,避免了调用者乱传参,保留了代码的通用性和独特性。

泛型类和泛型方法

一般使用大写字母声明泛型,例如<T>

类型擦除 Type erasure

思考:能否插入一个字符串元素到一个整型数组中?

答案:通过反射是可以的,原理就是类型擦除。

add(E e)方法在字节码文件中显示的是add(Object o)

什么是类型擦除?

Java泛型机制是在编译级别实现的,通过编译后,编译器就会将泛型给擦除掉。到了运行阶段时,对于JVM来说便没有了泛型类型的对象,其中的泛型参数都会被替换成它的第一个上界或Object,这个过程称为泛型擦除。

为什么要有类型擦除?

这是为了兼容jdk5以前的代码。

Java 泛型弊端

较之其他语言,Java的泛型存在的弊端有:

  1. 不支持基本类型:泛型最终会被擦除成具体类型,而Object不能存储基本数据类型
  2. 只有原始类型的class:只能对原始类型进行检测,无法判断带泛型的类型(jdk17中可以判断)
  3. 不能实例化泛型参数:因为运行时无法确定具体类型
  4. 不能实例化泛型数组:类型擦除会让实例化的数组成为Object[]

变型 Variant

协变 Covariant

如果B是A的子类,F(B)也是F(A)的子类。

逆变 Contravariant

如果B是A的子类,F(B)是F(A)的父类。

不变 Invariant

如果B是A的子类,F(B)和F(A)无关。

 

在Java中,泛型默认是不变的;而数组支持协变。那么是否可以让泛型支持逆变和协变呢?答案是可以的。

泛型的协变和逆变

协变和上界

使用通配符?和关键字extends,定义泛型的上界,来实现协变。

可以想象,协变存在类型安全隐患,泛型为了杜绝这种隐患采取一刀切的方式:只要声明了上界,就不允许插入null以外的元素。

逆变和下界

 使用通配符?和关键字super,定义泛型的下界,来实现逆变。

PECS原则

作为元素的生产者Producer,要用extends声明上界支持协变,以便获取元素;

作为元素的消费者Consumer,要用super来声明下界支持逆变,以便新增元素。

应用

一个典型的应用是Collections类的copy方法:

  • 协变适用于只读不写的场景。
  • 逆变适用于只写不读的场景。
  • 既要读有要写时,使用不变。

桥接方法

泛型方法重写

 

重写父类泛型方法时,在子类方法的入参类型和父类不一致,似乎违背了重写的原则(返回类型,方法名,参数列表都相同),但依然重写成功。

这是因为编译时生成了桥接方法setValue(Object)去调用子类方法setValue(String)

子类方法重写

顺便一提,当子类重写方法的返回类型是父类方法返回类型时的子类时,编译器也会自动生成桥接方法。

标签:Java,子类,类型,擦除,协变,泛型
From: https://www.cnblogs.com/-ori/p/17498788.html

相关文章

  • Java学习-集合篇
    集合什么是集合?有什么用?数组其实就是一个集合。集合实际上就是一个容器。可以来容纳其他类型的数据。集合为什么说在开发中使用的较多?集合是一个容器,是一个载体,可以依次容纳多个对象。在实际的开发中,假设连接数据库,数据库当中有10条记录,那么假设把这10条记录查询出来,在java程......
  • java线程的五种状态
    五种状态开始状态(new)就绪状态(runnable)运行状态(running)阻塞状态(blocked)结束状态(dead)状态变化1、线程刚创建时,是new状态2、线程调用了start()方法后,进入runnable状态,此时并未真正执行,需要和其他线程竞争cpu资源3、当该线程竞争到了cpu资源,进入running状态4、线程因为某种......
  • Java中 = 和 += 的区别
    问题shorts1=1;s1=s1+1;有什么错?shorts1=1;s1+=1;有错吗?讨论1)+:在编译器将右边的表达式结果计算出来后,和左边的变量类型比较精度,如果左边的变量精度低于右边的结果的精度,编译器会显式的报错,告诉程序员去强制转型。(所以s1=s1+1出错)最后将表达式的结果复......
  • Java基础:自动装箱和自动拆箱
    感谢,原文链接:https://www.cnblogs.com/dolphin0520/p/3780005.htmlJava的自动包装类型首先基本数据类型:4类8种基本数据类型对应包装器类byte(1字节)Byteshort(2字节)Shortint(4字节)Integerlong(8字节)Longfloat(4字节)Floatdouble(8字节)Doublechar(2字......
  • 现实中的 JAVA (一)
    买零食描述本例子主要是通过JAVA语言来描述,平时父母带我们去买零食的场景。买零食流程图从家里出发,选择一种出行方式达到零食店然后我们就可以开始购物了,选择对应的零食随后进行买单家庭成员UML图1、Person做为顶级的抽象类2、Male作为男CLass的描述类3、Fem......
  • JAVA博客3
     一.前言第三次写Blog,相比较上一次而言自己的经验更加的丰富了,这次blog的书写相对来说要更为轻松些。内容上题目较少,只需要分析有关课程成绩统计系统,但是说容易也并不容易,每一道题都是刺头中的刺头,这一次写博客,不仅仅是以完成任务的目的,更多的,让自己重新对那些打击过自己,折磨过......
  • java中的各种锁
    java中的各种锁一、概述乐观锁CAS悲观锁synchronized自旋锁CAS可重入锁synchronized、Reentrantlock、Lock读写锁ReentrantReadWriteLock,CopyOnWriteArrayList、CopyOnWriteArraySet公平锁Reentrantlock(true)非公平锁synchronized、reentrantlock(false)共享锁......
  • Java Web自定义MVC框架详解
    最近给学生讲JavaWeb,希望他们能够在学完这部分内容后自己实现一个MVC框架。但是突然发现百度上能搜索到的靠谱的资料并不是很多,有些只是原理没有代码实现,有些有代码实现但是对于初学者来说理解起来还是比较困难,于是决定把自己讲自定义MVC框架的内容放在这里分享给大家,不仅仅是代码......
  • 字符编码和Java中的乱码问题
    ASCII码  在计算机内部,所有的信息最终都表示为一堆二进制形式的数据。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,称为一个字节(byte),从0000000到11111111。上世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系做了统一规定,称之为ASCII......
  • Java Web项目中使用Freemarker生成Word文档
    Web项目中生成Word文档的操作屡见不鲜,基于Java的解决方案也是很多的,包括使用Jacob、ApachePOI、Java2Word、iText等各种方式,其实在从Office2003开始,就可以将Office文档转换成XML文件,这样只要将需要填入的内容放上${}占位符,就可以使用像Freemarker这样的模板引擎将出现占位符的地......