泛型
-
允许在定义接口、类、方法时使用类型形参,类型形参在整个接口、类体、方法内可当成类型使用,这个类型形参将在声明变量、创建对象、调用方法时动态的制定(即传入实际的类型参数、类型实参)
-
传入实际的类型参数不能是基本数据类型
:泛型要求包容的是对象类型,基本数据类型不是对象。int、double等基本数据类型的父类不是object类型(他们本身也没有父类),所以基本数据类型不是对象
原因:泛型<…>会在编译期间进行泛型擦除(将原来的数据类型变为object类型),nt、double等基本数据类型的父类不是object类型。
-
基本数据(如int、double)的封装类型(如Integer 、Double),可以作为泛型包容对象。
-
编译器会将泛型代码转换为普通的非泛型代码
-
常见的类型形参:T、E、K、V等
-
泛型的意义和作用
- 类型的参数化,可以将类型像方法的参数那样传递
- 提高类型安全
定义泛型接口、类
在创建带泛型声明的自定义类中定义构造器时,不要增加泛型声明
定义泛型类:
public class MyGenericClass<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
定义泛型接口:
public class MyGenericClass<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
泛型方法
- 在声明方法定义一个或多个参数形参,放在方法修饰符和方法返回值类型之间
- 方法中的泛型参数无需显示传入实际类型参数,编译器会根据实参推断类型形参的值
修饰符 <T, S> 返回值类型 方法名(形参列表) {
//方法体
}
类型通配符
- 使用类型通配符,如:List (表示元素类型未知的 List)、Set、Collection、Map
- 无界通配符(?):表示未知的类型,可以作为方法参数、返回值或局部变量使用。例如:
public <T> void print(List<?> list) {
for (Object item : list) {
System.out.println(item);
}
}
- 上界通配符(extends):表示类型必须是指定类型的子类或相同类型。例如:
public <T extends Number> double getAverage(List<T> list) {
double sum = 0;
for (T item : list) {
sum += item.doubleValue();
}
return sum / list.size();
}
- 设定类型通配符的下限
// TreeSet<E> 中的一个构造器// 表示所有以 E 为子类的类型TreeSet(Comparator<? super E> c)