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 Task定时任务的配置和使用详解

    Spring Task定时任务的配置和使用详解

    本篇文章主要介绍了Spring Task定时任务的配置和使用详解,实例分析了Spring Task定时任务的配置和使用的技巧,非常具有实用价值,需要的朋友可以参考下
    2017-04-04
  • 完美解决java读取大文件内存溢出的问题

    完美解决java读取大文件内存溢出的问题

    下面小编就为大家带来一篇完美解决java读取大文件内存溢出的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Java中常见死锁与活锁的实例详解

    Java中常见死锁与活锁的实例详解

    这篇文章主要介绍了Java中常见死锁与活锁的实例详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • java实现人民币大小写转换方法分享

    java实现人民币大小写转换方法分享

    本文介绍java人民币数字大小写转换方法,代码中有注释,大家直接看代码吧
    2014-01-01
  • Spring Bean的生命周期详细介绍

    Spring Bean的生命周期详细介绍

    这篇文章主要介绍了Spring Bean的生命周期的相关资料,需要的朋友可以参考下
    2016-09-09
  • Spring security密码加密实现代码实例

    Spring security密码加密实现代码实例

    这篇文章主要介绍了Spring security密码加密实现代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • java反射深入剖析(推荐)

    java反射深入剖析(推荐)

    下面小编就为大家带来一篇java反射深入剖析。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07
  • Java字符串原理分析之String是否可变

    Java字符串原理分析之String是否可变

    当我们在求职时,面试官很喜欢问我们关于String的一些原理性知识,比如String的不可变性、字符串的内存分配等,为了让大家更好地应对面试,并理解String的底层设计,接下来会给大家聊聊String的一些原理,比如String为什么具有不可变性,需要的朋友可以参考下
    2023-05-05
  • spring boot security设置忽略地址不生效的解决

    spring boot security设置忽略地址不生效的解决

    这篇文章主要介绍了spring boot security设置忽略地址不生效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • java处理按钮点击事件的方法

    java处理按钮点击事件的方法

    下面小编就为大家带来一篇java处理按钮点击事件的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04

最新评论