一、泛型概述
泛型,即是参数化类型。在没有泛型前,构建Object类型的集合可能出现ClassCastException。而在jdk5引入泛型后,便可以在编译器实现类型检查(实际为编译器语法糖,虚拟机没有泛型对象,所有对象都属于普通类)
泛型标识符一般为 T,E,K,V
二、泛型定义
(1)泛型类
代码示例:
public class Generic <T>{
private T num;
public T getNum() {
return num;
}
public void setNum(T num) {
this.num = num;
}
}
public class GenericTest {
public static void main(String[] args) {
// 按给定泛型决定
Generic<String> gen1 = new Generic<>();
gen1.setNum("hahaha");
Generic<Integer> gen2 = new Generic<>();
gen2.setNum(5);
}
}
注意:
- 类型参数不能是基本数据类型
- 没指定具体数据类型,默认为Object
- 泛型类型逻辑上是不同类型,实际是相同类型(getClass形同)
从泛型类派生子类:
- 子类是泛型类,子类和父类泛型类型要一致
- 子类不是泛型类,父类需要明确泛型类型
public class A<T> extends B<T>{}
public class A extends B<Integer>{}
(2)泛型方法
代码示例:
public class Generic{
private int num;
public <T> void show(T t){
System.out.println(t);
}
}
public class GenericTest {
public static void main(String[] args) {
Generic gen = new Generic();
// 由参数类型决定
gen.show("hahaha");
gen.show(555);
}
}
注意:
- 在泛型类中
public T getNum()
是成员方法而不是泛型方法,只有public void show(T t)
带<>的才是泛型方法 - 成员方法无法定义为static,泛型方法可以
- 在调用方法的时候定义类型,与泛型类中的类型无关
2.1 泛型可变参数
// 此时t为数组
public <T> void show(T ...t){
for (T t1 : t) {
System.out.println(t1);
};
}
t为数组,可以传任意多的值
gen.show(1,2,3,4,5);
(3)泛型接口
代码示例:
public interface Genericinf<T>{
public abstract void show(T t);
}
/**
*实现类
*/
public class Genericimpl<T> implements Genericinf<T>{
@Override
public void show(T t) {
System.out.println(t);
}
}
public class GenericTest {
public static void main(String[] args) {
new Genericimpl<String>().show("hahaha");
new Genericimpl<Integer>().show(555);
}
}
三、泛型使用
(1)类型通配符
(在使用泛型类,泛型接口时)
?为类型实参,而非类型形参
Generic<?> generic = new Generic();
四、泛型擦除
泛型类
泛型方法
泛型接口
桥接方法由编译器自动提供,保持接口和类的实现关系
通过反射可以验证:
/**
* 定义泛型接口
* @param <T>
*/
public interface Generic<T>{
T show(T t);
}
/**
* 实现类
*/
public class Genericimpl<T> implements Generic<Integer>{
@Override
public Integer show(Integer integer) {
return integer;
}
}
/**
* 利用反射机制验证
*/
public class GenericTest4 {
public static void main(String[] args) {
Class<Genericimpl> class1 = Genericimpl.class;
// 获取所有方法
Method[] declaredMethods = class1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
// 打印方法名和返回值类型
System.out.println(declaredMethod.getName()+":"+declaredMethod.getReturnType().getSimpleName());
}
}
}
结果:
五、泛型数组
在定义时只能声明带泛型的数组应用,不能创建带泛型的数组对象
ArrayList<String>[] a = new ArrayList[10]; // true
ArrayList<String>[] b = new ArrayList<String>[10]; // false