别再让类型限制你的代码!【Java包装类+泛型】,让数据结构开发一步到位
🎁个人主页:User_芊芊君子
🎉欢迎大家点赞👍评论📝收藏⭐文章
🔍系列专栏:Java.数据结构
【前言】
在Java中,包装类为基本数据类型提供对象封装,实现基本类型与对象的无缝转换;泛型则通过类型参数化,实现代码的通用复用并在编译期保证类型安全。二者结合,让数据结构能灵活适配多种类型,同时兼顾安全性与开发效率,是Java实现高效、通用数据操作的核心技术组合。
文章目录:
一、包装类
1. 什么是包装类?
包装类是Java中为8种基本数据类型提供的对应的类类型。它们位于java.lang包中,主要目的是将基本类型"包装"成对象,以便解决某些特殊场景。包装类实现了基本数据类型与对象之间的转换机制。
2.基本数据类型与包装类对应表
| 基本数据类型 | 包装类 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
3.装箱和拆箱
装箱:将基本类型转换为包装类的过程拆箱:包装类转换为基本类型的过程
int i =10;Integer j =Integer.valueOf(i);//手动装箱int m = j.intValue();//手动拆箱- 自动装箱和自动拆箱
int a =10;Integer b = a;//自动装箱Integer c =(int)a;//自动装箱【注意】
Integer 类型(默认范围:[-128~127])
超过范围就会新建对象
这时,a=200;b=200
如果打印a==b会返回false
publicstaticvoidmain(String[] args){Integer a =180;Integer b =180;System.out.println(a == b);}
二、泛型
1.什么是泛型?
泛型(Generics)是编程语言中一种强大的特性,一般的类和方法只能使用具体的类型,而泛型可以编写适用于多种数据类型的代码,而不需要为每种类型重复编写相似的代码。泛型的主要目的是提高代码的复用性、类型安全性以及代码的清晰度。
2.基本语法
class 泛型类名称<类型形参列表>{}classTest<T>{}其他写法:
class 泛型类名称<类型形参列表>extends 继承类<这里可以使用类型参数>3.引出泛型
实现一个类,该类中有一个可以存储任何类型数据的数组,并通过方法设置数组中的值,获取数组中的内容
publicclassArray{publicObject[] array =newObject[10];publicObjectgetPos(int pos){returnthis.array[pos];}publicvoidsetVal(int pos,Object val){this.array[pos]= val;}}publicstaticvoidmain(String[] args){Array myArray =newArray(); myArray.setVal(0,10); myArray.setVal(1,"bba");String ret =(String) myArray.getPos(0);//强制类型转换System.out.println(ret);}我们创建了一个Object类型的数组,可以存储任何类型的数据,因为Object是所有类型的父类,然后通过方法设置数组内容,但获取数据类型时会报错,发生了向下转型,这时要强制类型转换才能解决。这时,使用泛型则会更加便捷一点
使用泛型代码如下:
publicstaticvoidmain(String[] args){Array myArray =newArray(); myArray.setVal(0,10); myArray.setVal(1,"bba");//字符串也可以存放String ret =(String) myArray.getPos(0);//编译报错System.out.println(ret);}publicstaticvoidmain(String[] args){Array<String>myArray =newArray<String>(); myArray.setVal(1,"bba");String ret = myArray.getPos(0);System.out.println(ret);}< T >:就是占位符,表示当前类是一个泛型类;
类型后的< Integer >指定当前类型,后面就不需要强制类型转换
4.泛型的使用
泛型类<类型实参>变量名;//定义一个泛型类引用new 泛型类<类型实参>(构造方法实参);//实例化一个泛型类对象 eg:Array<Integer> list =newArray<Integer>();后面的new< >里面的包装类可以不写,编译器会根据前面的包装类自动推导
【注意】:泛型只能接受类,所有的基本数据类型必须使用包装类
5.擦除机制
泛型是编译时期的机制,代码运行时没有泛型这个概念
擦除机制:
在编译时,Java编译器会将泛型类型信息从代码中移除,这个过程就叫做类型擦除。擦除后,泛型类型会被替换为其边界类型(通常是Object)或者指定的类型。在必要的地方插入类型转换来保证类型安全生成桥接方式以保持多态性
上面的代码擦除后:
classMyArray{publicObject[] array =newObject[10];publicObjectgetPos(int pos){returnthis.array[pos];}}publicvoidsetVal(int pos,Object val){this.array[pos]= val;}5.泛型的上界
5.1语法
class 泛型类名称<类型形参 extends 类型边界>{...}eg1:
publicclassArray<EextendsNumber>{...}E 要么是Number的子类,要么是Number自己
eg2:
publicclassMyArray<EextendsComparable<E>>{...}E必须是实现了Comparable接⼝
5.2 示例
写一个泛型类,有一个方法,求T类型数组中最大值,数组没有指定类型
T类型是引用类型不能通过><==比较T类型擦除成Object,没有Comparable接口,所有要限定一下,给它一个上界
publicclassAlg<TextendsComparable<T>>{//T类型擦除成Object,没有Conmarable接口,所有要限定一下,给它一个上界publicTfindMaxVal(T[] array){T max = array[0];for(int i =0; i < array.length; i++){if(array[i].compareTo(max)>0){//T类型是引用类型不能通过><==比较 max = array[i];}}return max;}}publicstaticvoidmain(String[] args){Alg<Integer> alg =newAlg<>();Integer[] array ={5,88,9,6,56,4};int ret = alg.findMaxVal(array);System.out.println(ret);}6.泛型方法
6.1语法
⽅法限定符 <类型形参列表> 返回值类型⽅法名称(形参列表){...}6.2 示例
泛型方法可以是static ,也可以不是static
静态方法不需要实例化引用对象,可直接调用,但参数没办法传入,so:static后面写
classAlg2{publicstatic<TextendsComparable<T>>TfindMaxVal(T[] array){T max = array[0];for(int i =0; i < array.length; i++){if(array[i].compareTo(max)>0){//T类型是引用类型不能通过><==比较 max = array[i];}}return max;}}publicstaticvoidmain(String[] args){Integer[] array ={5,88,9,6,56,4};int ret =Alg2.findMaxVal(array);System.out.println(ret);}7.通配符
? ⽤于在泛型的使⽤,即为通配符,用于表示未知类型
? extends 类:设置通配符上限 ,表示类型必须是T或其子类
? super 类:设置通配符下限,表示类型必须是T或其父类
【总结】
通过以上对Java包装类和泛型的详细介绍,我们可以看到它们在Java编程中的重要性和广泛应用。掌握好这两个知识点,对于编写高效、安全、可复用的Java代码具有重要意义。