带大家认识Java语法之泛型与通配符
300
2022-08-18
Java 泛型考古 泛型擦除 包装类详细解析
目录一. 什么是泛型二. 为什么要有泛型 ?示例三、泛型考古四、泛型擦除五、包装类六、装箱拆箱
一. 什么是泛型
泛型(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
// 在类的实现中,可以直接将类当成一种数据类型来使用。在实例化该类的时候这个类型才被确定
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[]oYxKfFHGZ args) {
MyArrayList myArrayList = new MyArrayList();
myArrayList.add(1);
myArrayList.add(2);
oYxKfFHGZ // 这里其实就相当于是将String类型赋值给E
MyArrayList2
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来实现的
如下图
我们虽然用的是泛型,但其实泛型只存在于编译阶段,在编译过程中也伴随着泛型擦除,在生成.class文件的时候泛型信息就已经不存在了,成了JDK1.5之前的Object方式
查看MyArrayList的字节码文件就可以看出来
所以Java的泛型只存在于编译阶段(Java核心原理:Object引用可以指向任意类型的对象)
五、包装类
由于8种基本类型不是类类型,Java专门为它们定义了各自的包装类
如下:
byte java.lang.Byteshort java.lang.Shortchar java.lang.Characterint java.lang.Integerlong java.lang.Longfloat java.lang.Floatdouble java.lang.Doubleboolean java.lang.Boolean
六、装箱拆箱
Java中提供了便利,如果没有歧义,Java 会帮我们自动装箱,自动拆箱
Integer a = 10; // 把int赋值给Integer类型,隐含着发生了装箱过程
int b = a; // 把Integer赋值给int类型,隐含着发生了拆箱过程
隐式装箱和拆箱过程只存在于编译阶段,编译完成就变成显式装箱,显式拆箱了
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~