1. 泛型多边界
- 语法
<T extends A & B & C>
- 一个 class 边界 + 多个接口边界
- 第一个是类,& 后面的只能是接口(即:单继承 多实现)
https://developer.aliyun.com/article/24356
https://www.jianshu.com/p/0f2a9b9afde4
2. 泛型类派生子类
// 2.1 子类也是泛型,子类和父类的泛型标识要一致
public class ResultDTO<T, S> extends Result<T, S> {
}
ResultDTO<QueryDTO, QueryVO> resultDTO = new ResultDTO<>();
// 2.2 子类不是泛型类,父类要明确泛型的数据类型
public class ResultDTO extends Result<QueryDTO, QueryVO> {
}
ResultDTO resultDTO = new ResultDTO();
3. 获取泛型参数类型
3.1 继承泛型类
public class Result<T, S> {
}
public class ResultDTO extends Result<QueryDTO, QueryVO> {
}
public static void main(String[] args) {
ParameterizedType parameterizedType = (ParameterizedType) ResultDTO.class.getGenericSuperclass();
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type genericParameterType : actualTypeArguments) {
// 注意 genericParameterType.getClass() 是得到 class 文件信息,不能使用这种方式
Class clazz = (Class) genericParameterType;
}
Class<QueryDTO> queryDTOClass = (Class<QueryDTO>) actualTypeArguments[0];
Class<QueryVO> queryVOClass = (Class<QueryVO>) actualTypeArguments[1];
String beanName = queryVOClass.getName();
String className = queryVOClass.getSimpleName();
}
3.2 实现泛型接口
public interface Result<T, S> {
}
public class ResultDTO implements Result<QueryDTO, QueryVO> {
}
public static void main(String[] args) {
/**
* Type[] genericInterfaces = ResultDTO.class.getGenericInterfaces();
* Type[] 数组,代表类实现的多个接口
* ResultDTO implements Result<QueryDTO, QueryVO> {} 只实现了一个接口,取第一个元素
*/
Type genericInterface = ResultDTO.class.getGenericInterfaces()[0];
ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Class<QueryDTO> queryDTOClass = (Class<QueryDTO>) actualTypeArguments[0];
String beanName = queryDTOClass.getName();
}
4. 泛型擦除
Java 泛型是 1.5 引入,为了兼容 1.5 之前的代码,在编译器里通过擦除来支持泛型
例如:
List<Integer> intList = new ArrayList<>();
List<String> strList = new ArrayList<>();
// intList.getClass().getName() 和 strList.getClass().getName() 都是 java.util.ArrayList
System.out.println(intList.getClass() == strList.getClass()); // true
List<String>.class、List<Integer>.class 在 JVM 层面只有 List.class
// public TypeVariable<Class<T>>[] getTypeParameters() {}
List<User> users = new ArrayList<>();
System.out.println(Arrays.toString(users.getClass().getTypeParameters())); // [E]
getTypeParameters 返回类型参数,查看上面并不是返回 Integer,而是 [E] (一个占位符)
编译后查看 class 文件
进入class目录 javap -v xxx.class
or javap -v xxx
(文件后缀.class可省略)
List<Person> list = new ArrayList<>();
// javap 编译后,泛型 Person 被擦除 (泛型Person 并不是字节码中的指令,只是个符号,编译后被擦除)
Code:
stack=2, locals=2, args_size=1
0: new #2 // class java/util/ArrayList(编译后只是 ArrayList)
网友评论