Java 泛型考古 泛型擦除 包装类详细解析

 更新时间:2022年03月23日 10:20:58   作者:来自爪哇的bean  
泛型是在Java SE 1.5引入的的新特性,本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法,本篇我们一起来学习泛型考古、泛型擦除、包装类

一. 什么是泛型

泛型(generic type)其本质是将类型参数化,也就是说所操作的数据类型被指定为一个参数这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

二. 为什么要有泛型 ?

之前写过MyArrayList顺序表,这个类当时自己在实现的时候只能用一种类型来表示,也就是用的时候自己实现的MyArrayList只能应用于一种类型,要想应用于其他类型,就得再写一个其他类型的MyArrayList,这样就比较麻烦,而有了泛型之后就很好的解决了这个问题,让类型参数化,使得自己写的MyArrayList可以适用于多种场景

通过以下代码对比就可发现泛型的方便之处

示例

不带泛型

public class MyArrayList {
    private int[] array;
    private int size;    // 有效数据个数
    public MyArrayList() {
        this.array = new int[10];
        this.size = 0;
    }
    public void add(int x) {    // 暂不考虑扩容
        this.array[size] = x;
        this.size++;
    }
}

带泛型

import org.omg.CORBA.Object;

public class MyArrayList2<E> {
    // 在类的实现中,可以直接将类当成一种数据类型来使用。在实例化该类的时候这个类型才被确定
    private E[] array;
    private int size;   // 有效数据个数
    public MyArrayList2() {
        this.array = (E[])new Object[10];   // 注意:Java中泛型不允许定义数组
        this.size = 0;
    }
    public void add(E e) {    // 不考虑扩容
        this.array[size] = e;
        this.size++;
    }
}
// 带泛型的顺序表元素类型是一个“变量”
// E就是变量的名称

通过上面这两段代码的对比,就可以发现,带泛型的顺序表和不带泛型的顺序表只是表示类型的部分不一样,代码所实现的逻辑是一样的

类的实例化与使用

public static void main(String[] args) {
    MyArrayList myArrayList = new MyArrayList();
    myArrayList.add(1);
    myArrayList.add(2);
																	// 这里其实就相当于是将String类型赋值给E
    MyArrayList2<String> stringMyArrayList2 = new MyArrayList2<String>();    // 等号右边的<>内可以省略
    stringMyArrayList2.add("1");                                           // 要想用基本类型,要写基本类型对应的包装类
    stringMyArrayList2.add("2");
}

对于泛型来说,类型是在使用该类时才明确定义出来的

三、泛型考古

要知道其实刚开始Java体系中是没有泛型的,是在JDK1.5之后才才有了泛型

在JDK1.5之前是利用Object引用可以指向任意类型的对象实现类似泛型的效果

  • Object类是所有类的祖先类
  • 上层引用可以指向下层对象

如下代码:

public class MyArrayList3 {
    private Object[] array;
    private int size;
    public MyArrayList3() {
        this.array = new Object[10];
        this.size = 0;
    }
    public void add(Object e) {
        this.array[size] = e;
        size++;
    }
}

这种做法的缺点也很明显,就是new了一个MyArrayList,里面打算存int类型的数据,但由于手滑,存入了一个String类型的数据,这样的话编译器是不会报错的,程序也能正常运行,直到需要取list中的元素的时候程序才会抛出异常。

泛型就很好的解决了这个问题,只要类型不匹配,错误会在第一时间暴露出来

四、泛型擦除

虽然在 JDK1.5 之后有了泛型,但其实JDK的底层实现还是用的上面Object来实现的

如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sB60DwZz-1646265098596)(C:\Users\LY\AppData\Roaming\Typora\typora-user-images\image-20211210185132787.jpg)]

我们虽然用的是泛型,但其实泛型只存在于编译阶段,在编译过程中也伴随着泛型擦除,在生成.class文件的时候泛型信息就已经不存在了,成了JDK1.5之前的Object方式

查看MyArrayList的字节码文件就可以看出来

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KCvl7iYr-1646265098598)(C:\Users\LY\AppData\Roaming\Typora\typora-user-images\image-20220123202400988.jpg)]

所以Java的泛型只存在于编译阶段(Java核心原理:Object引用可以指向任意类型的对象)

五、包装类

由于8种基本类型不是类型,Java专门为它们定义了各自的包装类

如下:

byte java.lang.Byte
short java.lang.Short
char java.lang.Character
int java.lang.Integer
long java.lang.Long
float java.lang.Float
double java.lang.Double
boolean java.lang.Boolean

六、装箱拆箱

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dsPrxxd0-1646265098599)(C:\Users\LY\AppData\Roaming\Typora\typora-user-images\image-20220212173816723.jpg)]

Java中提供了便利,如果没有歧义,Java 会帮我们自动装箱,自动拆箱

Integer a = 10;   // 把int赋值给Integer类型,隐含着发生了装箱过程
int b = a;      // 把Integer赋值给int类型,隐含着发生了拆箱过程

隐式装箱和拆箱过程只存在于编译阶段,编译完成就变成显式装箱,显式拆箱了

到此这篇关于Java 泛型考古 泛型擦除 包装类详细解析的文章就介绍到这了,更多相关Java 泛型 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • spring boot application properties配置实例代码详解

    spring boot application properties配置实例代码详解

    本文通过代码给大家介绍了spring boot application properties配置方法,需要的的朋友参考下吧
    2017-07-07
  • Java数据结构二叉树难点解析

    Java数据结构二叉树难点解析

    树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构,很象自然界中的树那样。树结构在客观世界中广泛存在,如人类社会的族谱和各种社会组织机构都可用树形象表示
    2021-10-10
  • Java中管理资源的引用队列相关原理解析

    Java中管理资源的引用队列相关原理解析

    这篇文章主要介绍了Java中管理资源的引用队列相关原理解析,涉及到Java的垃圾回收机制方面的知识,需要的朋友可以参考下
    2015-12-12
  • java实现计算周期性提醒的示例

    java实现计算周期性提醒的示例

    本文分享一个java实现计算周期性提醒的示例,可以计算父亲节、母亲节这样的节日,也可以定义如每月最好一个周五,以方便安排会议
    2014-04-04
  • SpringBoot2.0 整合 Dubbo框架实现RPC服务远程调用方法

    SpringBoot2.0 整合 Dubbo框架实现RPC服务远程调用方法

    这篇文章主要介绍了SpringBoot2.0 整合 Dubbo框架 实现RPC服务远程调用 ,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-07-07
  • 关于maven使用过程中无法导入依赖的一些总结

    关于maven使用过程中无法导入依赖的一些总结

    这篇文章主要介绍了关于maven使用过程中无法导入依赖的一些总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • springmvc项目使用@Valid+BindingResult遇到的问题

    springmvc项目使用@Valid+BindingResult遇到的问题

    这篇文章主要介绍了springmvc项目使用@Valid+BindingResult遇到的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Java中的Semaphore信号量使用方法代码实例

    Java中的Semaphore信号量使用方法代码实例

    这篇文章主要介绍了Java中的Semaphore信号量使用方法代码实例,Semaphore是一种基于计数的信号量,它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞,需要的朋友可以参考下
    2023-11-11
  • eclipse连接数据库并实现用户注册登录功能

    eclipse连接数据库并实现用户注册登录功能

    这篇文章主要介绍了eclipse连接数据库并实现用户注册登录功能的相关资料,需要的朋友可以参考下
    2021-01-01
  • Java 中的 Unsafe 魔法类的作用大全

    Java 中的 Unsafe 魔法类的作用大全

    Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,关于Java 中的 Unsafe 魔法类,到底有啥用处,你都了解吗,下面通过本文给大家普及一下
    2021-06-06

最新评论