JAVA泛型和擦拭
泛型
1、什么是泛型
泛型可以看作是一个模板,例如:ArrayList<T>
,每次用到的时候就创建对应的ArrayList<类型>
:
// 存储String的ArrayList:
ArrayList<String> strList = new ArrayList<String>();
// 存储Float的ArrayList:
ArrayList<Float> floatList = new ArrayList<Float>();
// 存储自定义类型Person的ArrayList:
ArrayList<Person> personList = new ArrayList<Person>();
注意:<>
中不能是基本数据类型
2、使用泛型
编写一个泛型
class Bird<T> {
private T name;
private T address;
private T[] elem; //泛型类型的数组
public Bird(T name,T address) {
this.name = name;
this.address = address;
this.elem = (T[])new Objects[10]; //创建数组时使用Objects类型,再强转为T[]类型
}
public T getName() {
return name;
}
public T getAddress() {
return address;
}
public void setName(T name) {
this.name = name;
}
public void setAddress(T address) {
this.address = address;
}
}
注意:定义泛型静态方法时需要在static
后加上<T>
public static<T> Bird<T> mesg(T name,T address){
return new Bird<>(name,address);
}
泛型可以定义多种类型,比如我们常用的Map<K,V>就是使用了两种泛型
3、通配符
<T extends 类型>
,称为上界通配符,例如:<T extends Number>
表示T
的类型,只能是Number
的子类或者本身,即Number
是T
类型的上界。
<T super 类型>
表示,方法参数接受所有类型为该类型本身或该类型的父类,例如<T super Integer>
,表示方法接受的类型为Integer
或者Integer
的父类。
擦拭法
擦拭法是指,我们定义的泛型类在执行时会被擦拭成Object
类型。即在运行时,泛型类的T会被擦成Object
,这就是为什么泛型类可以接收所有数据类型。所以,Java的泛型是由编译器在编译时实行的,编译器内部永远把<T>
当作Object
处理,但是,在需要转型的时候,编译器就会根据<T>
的类型安全地强制转型。
擦拭法地局限性:
<T>
不能是基本类型,因为实际类型是Object
,Object
类型无法持有基本类型。- 无法取得带泛型的class。因为T是Object,我们对
Bird<Integer>
和Bird<String>
使用getClass()
方法时,返回的是Bird
类的class
。因为他们编译之后都是Bird<Object>
。 - 无法判断带泛型的类型,即不能使用
instanceof
来判断一个对象是不是泛型类的实例。因为并不存在Bird<Integer>.calss
,只存在Bird.calss
。 - 不能实例化
T
类型,即new T()