接上一篇继续写
- 编译时类型检查
虽然泛型类在运行时进行了类型擦除,但在编译阶段,Java 编译器会对泛型代码进行严格的类型检查。
3-1 类型参数的约束
在定义泛型类时,可以对类型参数进行约束,例如指定类型参数必须是某个类的子类。
class NumberBox<T extends Number> {
private T number;
public void setNumber(T number) {
this.number = number;
}
public T getNumber() {
return number;
}
}
3-2 类型安全
通过编译时的类型检查,泛型类可以确保在使用时不会出现类型不匹配的问题。例如:
Box<Integer> integerBox = new Box<>();
// 编译错误,不能将 String 类型赋值给 Box<Integer>
// integerBox.setItem("hello");
- 桥方法(Bridge Methods)
由于类型擦除的存在,在某些情况下,为了保证泛型类的多态性,编译器会生成桥方法。
4-1 示例
一个泛型类的子类:
class IntegerBox extends Box<Integer> {
@Override
public void setItem(Integer item) {
super.setItem(item);
}
@Override
public Integer getItem() {
return super.getItem();
}
}
桥方法:
class IntegerBox extends Box<Integer> {
// 桥方法
@Override
public void setItem(Object item) {
setItem((Integer) item);
}
@Override
public Integer getItem() {
return super.getItem();
}
public void setItem(Integer item) {
super.setItem(item);
}
}
- 运行时获取泛型信息
虽然泛型类在运行时进行了类型擦除,但在某些情况下,仍然可以通过反射获取泛型信息。
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
class GenericClass<T> {
private List<T> list = new ArrayList<>();
public Type getGenericType() {
Type superclass = getClass().getGenericSuperclass();
if (superclass instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) superclass;
return parameterizedType.getActualTypeArguments()[0];
}
return null;
}
}
class StringGenericClass extends GenericClass<String> {}
public class Main {
public static void main(String[] args) {
StringGenericClass stringGenericClass = new StringGenericClass();
Type genericType = stringGenericClass.getGenericType();
System.out.println(genericType);
}
}