目录
包装类
基本数据类型与对应的包装类
装箱和拆箱
装箱
拆箱
泛型
什么是泛型
泛型的语法与使用
泛型的编译
擦除机制
泛型的上界
泛型方法
提到泛型的话,我们就先提一下包装类吧!
包装类
在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型。(注意int和char的包装类不是只大写第一个字母)
基本数据类型与对应的包装类
基本数据类型 | 包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
装箱和拆箱
装箱
装箱:把一个基本数据类型 转化为 包装类型的过程
装箱又分为自动装箱和显示装箱,但是都调用了valueof()方法。下面代码可以体现
eg:
public static void main(String[] args) {
int a = 10;
Integer b = a; //自动装箱
Integer c = Integer.valueOf(a); //显示装箱
}
拆箱
拆箱:把一个包装类型 转化为 基本数据类型的过程
拆箱也分为自动装箱和显示装箱。下面代码可以体现
eg:
public static void main(String[] args) {
Integer a = new Integer(10);
int b = a; //自动拆箱
int c = a.intValue(); //显示拆箱
double d = a.doubleValue();
}
泛型
什么是泛型
就是适用于许多许多类型。从代码上讲,就是对类型实现了参数化。
下面咱看一个问题:
实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值?
class MyArray {
//可以存放任何类型的话 定义一个Object数组
public Object[] array = new Object[10];
//pos放入的位置 val存放的数据
public void set(int pos, Object val) {
array[pos] = val;
}
//获取数据
public Object get(int pos) {
return array[pos];
}
}
但是这样写的话需要强转类型
那么怎么解决呢?
这就不得不提出泛型了
泛型的语法与使用
class 泛型类名称<类型形参列表> {
// 这里可以使用类型参数
}
作用:
1. 泛型是将数据类型参数化,进行传递
2. 使用 <T> 表示当前类是一个泛型类。
3. 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换
这样(代码体现)就能解决上面的问题了(可以不用强制类型转换)
class MyArray<T> {
//可以存放任何类型的话 定义一个Object数组
public Object[] array = new Object[10];
//pos放入的位置 val存放的数据
public void set(int pos, T val) {
array[pos] = val;
}
//获取数据
public T get(int pos) {
return (T)array[pos];
}
}
//测试类中的main方法
public static void main(String[] args) {
//<>里面只能放包装类型
MyArray<String> myArray1 = new MyArray<>();
MyArray<Integer> myArray2 = new MyArray<>();
}
注意:不能new一个泛型类的数组 但是可以下面这样写(不推荐)
class MyArray<T> {
public T[] array2 = new T[10]; //不能直接new(下面会解释)
public T[] array3 = (T[]) new Object[10];//不建议
}
泛型的编译
擦除机制
通过命令:javap -c 查看字节码文件,所有的T都是Object。在编译的过程当中,将所有的T替换为Object这种机制,我们称为:擦除机制。Java的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。
提出问题:
1.那为什么,T[] ts = new T[5]; 是不对的,编译的时候,替换为Object,不是相当于:Object[] ts = new Object[5]吗?
这是因为在Java中,泛型类型擦除机制会将T转换为Object,并且不支持创建泛型数组。
public class GenericArray<T> {
private T[] array;
public GenericArray(int size) {
this.array = new T[size]; // 编译错误
}
}
上述代码中,在使用new关键字创建GenericArray实例时,我们尝试创建一个大小为size的泛型数组。但是,由于类型擦除机制,编译器无法了解T的确切类型,因此无法创建泛型数组。
泛型的上界
语法:
实例:
这里的传入的类型形参(E)必须是边界(Number)的子类
求一个数组中的最大值想必大家都不陌生吧,那么大家看看下面的代码,为什么报错呢?
这里是因为呢,在编译的时候T会被替换成Object,但是在Object类中没有没有实现比较的接口,因为它是引用类型,必须 . 一个比较的方法,也得让T实现比较的接口。代码如下:
//这里extends是扩展的意思 不是继承的意思
class Alg<T extends Comparable<T>> {
public T findMax(T[] array) {
T max = array[0];
for (int i = 1; i < array.length; i++) {
if(array[i].compareTo(max) > 0) {
max = array[i];
}
}
return max;
}
}
泛型方法
语法:
示例:
//泛型方法 返回值为T类型
public static <T> T swap() {
}