数据结构–泛型(java版)
一.包装类:
1.基本数据类型对应的包装类:
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
注意int和char类型的包装类是Integer和Character,其它的基础数据类型可以直接首字母大写
2.装箱和拆箱:
其实也可以叫做装包和拆包
装箱:把基本数据类型转换成包装类型
Integer a=10;//法一自动装包
int i=99;
Integer b=i;//法二装包
System.out.println(a);
System.out.println(b);//都是可以直接打印的
拆箱:把包装类型转换为基本数据类型
Integer a=10;
int b=a;//拆箱
二.泛型:
1.泛型的定义:
简单的讲泛型,就是适用于很多类型,可以讲类型进行传递。从代码上讲,就是对类型实现了参数话
2.泛型的基本语法:
class 泛型类名称<类型型参列表>{
}
3.为什么使用泛型:
下面举一个例子:实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值
没用泛型之前的代码
class MyArray{
public Object[] array=new Object[10];
public Object getPos(int pos){
return this.array[pos];
}
public Object setPos(int pos,Object val){
this.array[pos]=val;
}
}
public class Test{
public static void main(String[] args){
MyArray myArray=new MyArray();
myArray.setPos(0,10);
myArray.setPos(1,"hello world");
String ret=myArray.getPos(1);//报错
System.out.println(ret);
}
}
如果按照上述代码的写法会发现出现了报错的现象
虽然在这种情况下任何数据类型都可以存储在这个数组中,但是更多情况下,我们还是希望它只能存储一种数据类型。
所以泛型的主要目的:就是指定当前的容器,要持有什么类型的变量,让编译器去做检查
下面对上面的例子用泛型来解决
class MyArray<T>{
public Object[] array=new Object[10];
public setValue(int pos,T val){
array[pos]=val;
}
public getValue(int pos){
return (T)array[pos];
}
}
public static void main(String[] args){
MyArray<Integer> myArray=new MyArray<>();
myArray.setValue(0,10);
myArray.setValue(1,100);
int a=myArray.getArray(1);
System.out.println(a);
MyArray<String> myArray2=new MyArray<>();
myArray2.setValue(2,"hello");
myArray2.setValue(3,"world");
String b=myArray2.getArray(2);
System.out.println(b);
}
这就是使用泛型来实现数组内存放不同数据类型的例子
在最开始的时候定义一个泛型类,这时一定要在泛型类名称后面加上,这时泛型的基础语法
注意:在定义数组时,必须使用Object,不能使用T来定义数组的类型,因为泛型时编译时期存在的,当程序运行起来到JVM之后,就没有泛型这个概念了
在定义setter时,传入数组中某一位的数据的类型,必须写成T类
在定义getter时,return回的数据必须强转成T类型
泛型本质上在编译的过程是擦除机制,就是把T擦出成了object
4.泛型类的使用:
(1)语法:
泛型类<类型参数>变量名;//定义了一个泛型类
MyArray<Integer> myArray=new MyArray<Integer>();//形容这种就是在实例化一个泛型类对象
(2)类型推导:
本质上就是简写
MyArray<Integer> myArray=new MyArray<>();
5.泛型上界:
这串代码就可以展现出上界的写法和上界的意义
首先泛型上界的写法,就是在T后面加上 extends 类型边界
其次泛型上界的意义就是在于限制数组中数据的类型,就如上面这串代码,先是定义泛型的上界是Number,也就是说,数组内的数据类型是整数或小数,不能是字符串,就像最后对MyArray类进行初始化时,最后一行代码使用想让数组内的数据类型变成字符串类型,但是有着上界的限制,所以最后回报错
6.练习:
例子:用泛型类实现找出数组最大的数据
class Alg<T extends Comparable<T>>{
public T findMax(T[] array) {
T max=array[0];
for(int i=0;i<array.length;i++){
if(max.compareTo(array[i])<0){
max=array[i];
}
}
return max;
}
}
public class Mode {
public static void main(String[] args) {
Alg<Integer> alg=new Alg<>();
Integer[] integers={1,2,3,4,5,6};
Integer ret=alg.findMax(integers);
System.out.println(ret);
}
}
这就是使用泛型类来找到数组中最大的数据
那么这时可以引入下一个知识点,就是使用泛型方法来找出数组最大的数据
class Alg2{
public <T extends Comparable<T>> T findMax(T[] array) {
T max=array[0];
for(int i=0;i<array.length;i++){
if(max.compareTo(array[i])<0){
max=array[i];
}
}
return max;
}
}
public class Mode2 {
public static void main(String[] args) {
Alg2 alg2=new Alg2();
Integer[] integers={1,2,3,4,5};
Integer ret1=alg2.findMax(integers);
System.out.println(ret1);
}
}
这串代码是使用泛型方法来实现找到数组中最大的数据
我们可以发现,使用泛型类和泛型方法都可以实现目的,但是两者是有差别的
对应泛型方法来说,T类是定义在方法里的,而方法类中T类是放在类当中的
还有就是在main方法里,使用泛型方法在实例化的时候是不用指定类型的,其实编译器自动帮助我们进行了指定,编译器回根据Integer ret1=alg2.findMax(integers);这句话里小括号内的数据类型,自动的推导出T的类型,所以这个就叫做类型推导
类型推导:根据实参传值来推导此时的类型