https://mp.weixin.qq.com/s/5oePzbAnV04aUOOcpw9VLA
getSuperclass()
返回直接继承的父类(由于编译擦除,没有显示泛型参数)
如果此 Class 表示 Object 类、一个接口、一个基本类型或 void,则返回 null。
如果此对象表示一个数组类,则返回表示该 Object 类的 Class 对象。
getGenericSuperclass()
这个可以用来获取所继承的超类的类型。返回的 Type,表示 Class 对象对应的实体(类、接口、基元类型或 void)的直接超类的 Type。
Type type1 = ArrayList.class.getGenericSuperclass();
System.out.println("ArrayList.class的超类的类型:"+type1.getTypeName());
// 下标0表示第1个参数,若有多个参数可递增
System.out.println("ArrayList.class的超类的泛型参数类型:"+((ParameterizedType)type1).getActualTypeArguments()[0]);
// 打印结果如下:
// ArrayList.class的超类的类型:java.util.AbstractList<E>
// ArrayList.class的超类的泛型参数类型:E
这个是只能获取直接超类(第一级超类)的类型,如果还需要获取超类的超类的类型,可以加上 getSuperclass()。
Type type1 = ArrayList.class.getSuperclass().getGenericSuperclass();
System.out.println("ArrayList.class的超类的超类的类型:"+type2.getTypeName());
// 下标0表示第1个参数,若有多个参数可递增
System.out.println("ArrayList.class的超类的超类的泛型参数类型:"+((ParameterizedType)type2).getActualTypeArguments()[0]);
// 打印结果如下:
// ArrayList.class的超类的超类的类型:java.util.AbstractCollection<E>
// ArrayList.class的超类的超类的泛型参数类型:E
getInterfaces()
返回直接实现的接口(由于编译擦除,没有显示泛型参数)
如果此对象表示一个类,则返回值是一个数组,它包含了表示该类所实现的所有接口的对象。数组中接口对象顺序与此对象所表示的类的声明的 implements 子句中接口名顺序一致
如果此对象表示一个接口,则该数组包含表示该接口扩展的所有接口的对象。数组中接口对象顺序与此对象所表示的接口的声明的 extends 子句中接口名顺序一致
如果此对象表示一个不实现任何接口的类或接口,则此方法返回一个长度为 0 的数组
如果此对象表示一个基本类型或 void,则此方法返回一个长度为 0 的数组
getGenericInterfaces()
这个可以用来获取所实现的接口的类型。返回的 Type,表示 Class 对象对应的类或接口所实现的接口的类型数组(因为 JAVA 中类可实现/接口可继承 N 个接口)。
// 下标0表示所实现接口中的第1个
Type type2 = ArrayList.class.getGenericInterfaces()[0];
System.out.println("ArrayList.class实现的第1个接口的类型:"+type2.getTypeName());
System.out.println("返回值type2本身的实际类型:"+type2.getClass());
// 实际类型为ParameterizedTypeImpl的,可以强转,继续获取泛型参数的类型;若为java.lang.Class,则表示不是泛型
System.out.println("ArrayList.class实现的第1个接口的泛型参数类型:"+((ParameterizedType)type2).getActualTypeArguments()[0]);
// 打印结果如下:
// ArrayList.class实现的第1个接口的类型:java.util.List<E>
// 返回值type2本身的实际类型:class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
// ArrayList.class实现的第1个接口的泛型参数类型:E
这个一样只能获取到直接实现的 N 个接口(第一级接口),如果需要获取所实现接口的所实现接口的类型,就需要将获取到的类型转为 Class 对象,再重复执行方法。如果是接口类型是泛型的,则不能用 getTypeName(),而是需要用 getRawType()。
try {
Class clazz = Class.forName(((ParameterizedType) type2).getRawType().getTypeName());
Type type3 = clazz.getGenericInterfaces()[0];
System.out.println("type3="+type3.getTypeName());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
// 打印结果如下:
// type3=java.util.SequencedCollection<E>
> 使用案例
?和 T 使用区别
特性
?
通配符
T
类型参数
含义
未知类型
特定但未确定的类型
实例化
不能创建实例
可以创建实例
类型安全
只能当作 Object 使用
可以当作具体类型使用
添加元素
通常不能添加
可以添加(类型安全)
读取元素
只能当作 Object 读取
可以当作具体类型读取
使用场景
只读操作、类型检查
需要创建实例、类型安全操作
选择使用 ? 还是 T 取决于你的具体需求:
如果只需要读取或检查类型信息,使用 ?
如果需要创建实例或进行类型安全的操作,使用 T
// 1. 代表未知类型
public void processClass(Class<?> clazz) {
// clazz 可以是 Class<String>、Class<Integer> 等任意类型
System.out.println(clazz.getName()); // 可以调用 Object 方法
// clazz.newInstance(); // 编译错误:无法创建实例
}
// 2. 只读操作安全
public void printList(List<?> list) {
for (Object item : list) { // 只能当作 Object 处理
System.out.println(item);
}
// list.add("abc"); // 编译错误:无法添加元素
}
// 1. 代表特定但未确定的类型
public <T> void processClass(Class<T> clazz) {
// T 是确定的类型,只是在编译时还不知道具体是什么
try {
T instance = clazz.newInstance(); // 可以创建实例
System.out.println(instance.getClass().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
// 2. 类型安全的操作
public <T> void copyList(List<T> source, List<T> target) {
for (T item : source) {
target.add(item); // 类型安全
}
}
统一 API 结果封装
// 定义泛型结果类
@Data
public class Result<T> {
private int code;
private String msg;
// 泛型字段,承载业务数据
private T data;
// 成功静态工厂方法
public static <T> Result<T> success(T data) {
return new Result<>(200, "success", data);
}
}
通用分页查询结果
@Data
public class PageResult<T> {
private long total;
private int pageNum;
private int pageSize;
// 泛型列表,存储分页数据
private List<T> list;
}
// 使用示例
public PageResult<Order> getOrdersByPage(int pageNum, int pageSize) {
List<Order> orderList = orderService.getOrders(pageNum, pageSize);
long total = orderService.countOrders();
return new PageResult<>(total, orderList, pageNum, pageSize);
}
extends 和 super 使用
通配符 ? 用于解决类型间的兼容性问题。<? extends T> 表示类型上限,只能获取元素;<? super T> 表示类型下限,只能插入元素。
class Animal {
}
class Dog extends Animal {
}
public class Main {
public static void main(String[] args) {
List<Dog> dogs = new ArrayList<>();
// 读取数据,使用? extends
readElements(dogs);
// 写入数据,使用? super
writeElement(dogs);
}
// 只能读取,不能写入
public static void readElements(List<? extends Animal> list) {
for (Animal animal : list) {
System.out.println(animal);
}
}
// 只能写入,不能读取
public static void writeElement(List<? super Dog> list) {
list.add(new Dog());
}
}
策略模式结合泛型
public interface Handler<T> {
// 判断是否支持处理该类型
boolean supports(Class<?> clazz);
// 处理数据
void handle(T data);
}
@Component
public class EcouponHandler implements Handler<Ecoupon> {
@Override
public boolean supports(Class<?> clazz) {
return Ecoupon.class.isAssignableFrom(clazz);
}
@Override
public void handle(Ecoupon ecoupon) {
// 处理电子券的专属逻辑
}
}
@Service
public class HandlerManager {
@Resource
private List<Handler<?>> handlers;
public <T> void process(T data) {
for (Handler<?> handler : handlers) {
if (handler.supports(data.getClass())) {
((Handler<T>) handler).handle(data); // 类型安全转换后处理
return;
}
}
throw new UnsupportedOperationException("无支持处理器");
}
}
获取类的超类或接口的 class 类型
public interface DealHandler<K, T> {
T getTValue(K k);
default Class<T> getTClass() {
// 获取实现类中的T的class类型
// 从父类中获取泛型参数
Type superclass = this.getClass().getGenericSuperclass();
if (superclass instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) superclass;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length > 1) {
System.out.println("从父类成功获取到类型");
return (Class<T>) actualTypeArguments[1];
}
}
// 如果从父类获取不到,则尝试从接口获取
Type[] genericInterfaces = this.getClass().getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
if (genericInterface instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments.length > 1) {
System.out.println("从接口成功获取到类型");
return (Class<T>) actualTypeArguments[1];
}
}
}
throw new UnsupportedOperationException("无法获取泛型类型T的Class");
}
}
public class DealHandlerImpl implements DealHandler<Integer, Double> {
@Override
public Double getTValue(Integer integer) {
return 0.0;
}
public static void main(String[] args) {
DealHandler<Integer, Double> dealHandler = new DealHandlerImpl();
Class<Double> tClass = dealHandler.getTClass();
System.out.println(tClass);
}
}
public abstract class DealHandlerTemplate<K, T> implements DealHandler<K, T> {
}
public class DealHandlerTemplateImpl extends DealHandlerTemplate<Integer, String> {
@Override
public String getTValue(Integer integer) {
return "";
}
public static void main(String[] args) {
DealHandlerTemplate<Integer, String> dealHandlerTemplate = new DealHandlerTemplateImpl();
Class<String> tClass = dealHandlerTemplate.getTClass();
System.out.println(tClass);
}
}