1. 什么是泛型
泛型(Generic)是Java编程语言的一项特性,允许类、接口和方法在定义时使用类型参数,从而可以在不确定具体类型的情况下编写代码。泛型的主要目的是提高代码的重用性和类型安全性。
2. 泛型的基本语法
- 泛型类:定义带有类型参数的类。
public class Box<T> {
private T value;
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
- 泛型方法:定义带有类型参数的方法。
public <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
- 泛型接口:定义带有类型参数的接口。
public interface Pair<K, V> {
K getKey();
V getValue();
}
3. 类型擦除
泛型在编译时会进行类型擦除(Type Erasure),即将泛型类型替换为它们的非泛型上界(通常是 Object
)。类型擦除的目的是确保与遗留代码的兼容性。
-
类型擦除的影响
:
- 不能直接实例化泛型类型,如
new T()
。 - 不能创建泛型类型的数组,如
new T[10]
。 - 运行时类型信息丢失,无法直接获取泛型参数的类型。
- 不能直接实例化泛型类型,如
4. 获取泛型类型信息
尽管类型擦除会导致泛型类型信息在运行时丢失,但可以通过反射和特定的技巧来获取泛型类型信息。
- 通过子类获取泛型类型:
public class GenericClass<T> {
public Class<T> getType() {
Type type = getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
return (Class<T>) pt.getActualTypeArguments()[0];
}
return null;
}
}
// 通过子类
public class StringGenericClass extends GenericClass<String> {
public static void main(String[] args) {
StringGenericClass instance = new StringGenericClass();
System.out.println(instance.getType()); // 输出: class java.lang.String
}
}
// 通过匿名子类
public void getType(){
GenericClass instance = new GenericClass<String>(){};
System.out.println(instance.getType()); // 输出: class java.lang.String
}
- 通过方法或字段获取泛型类型:
java复制代码import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public class 获取泛型类型_参数化类型<T> {
public String name;
T t;
public 获取泛型类型_参数化类型(T t) {
this.t = t;
}
@SuppressWarnings("unchecked")
public Class<?> getParameterizedType() {
return t.getClass();
}
public static void main(String[] args) {
获取泛型类型_参数化类型 parameterizedType = new 获取泛型类型_参数化类型<OriginBean>(new OriginBean());
parameterizedType.getParameterizedType();
System.out.println(parameterizedType);
}
}
5. 通配符
Java 泛型支持使用通配符 ?
来表示未知类型。常见的通配符有:
-
无界通配符:
<?>
表示任意类型。 -
有界通配符(上界):
<? extends T>
表示类型是T
或其子类。 -
有界通配符(下界):
<? super T>
表示类型是T
或其父类。
6. 泛型的限制
不能实例化泛型类型:不能使用 new T()
来实例化泛型类型。
不能创建泛型数组:不能使用 new T[10]
创建泛型数组。
不能直接使用基本类型作为泛型参数:例如,不能使用 List<int>
,而应使用 List<Integer>
。
7.子类继泛型父类
子类可以继承泛型父类,并可以选择在继承时指定具体的泛型类型,也可以继续保留泛型。
- 指定具体类型:
public class StringBox extends Box<String> {
// 子类的泛型类型已经确定为 String
}
- 继续保留泛型:
public class GenericBox<T> extends Box<T> {
// 子类继续保留泛型 T
}
8. 泛型的应用场景
- 集合框架:Java 的集合框架广泛使用了泛型,以实现类型安全和代码重用。
- 类型安全的容器:泛型允许创建类型安全的容器类。
- 通用算法:可以编写适用于不同类型的通用算法。