Java 在运行时获取泛型类型:在某些情况下有效,但在其他情况下无效-为什么?
我正在尝试获取类或接口实现的泛型类型。我知道这有一些风险和怪癖,但我正在努力理解什么是可能的 下面是我的示例代码:Java 在运行时获取泛型类型:在某些情况下有效,但在其他情况下无效-为什么?,java,generics,dynamic,Java,Generics,Dynamic,我正在尝试获取类或接口实现的泛型类型。我知道这有一些风险和怪癖,但我正在努力理解什么是可能的 下面是我的示例代码: import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Arrays; import java.util.LinkedList; public class Main { public interface MyInterface<T>
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.LinkedList;
public class Main {
public interface MyInterface<T> {
}
public static class BaseImpl<T> implements MyInterface<T> {
}
public static class TypedImpl extends BaseImpl<Integer> {
}
public static void main(String[] args) throws Exception {
LinkedList<MyInterface<Integer>> instances = new LinkedList<>();
// 1. anonymous class from interface
instances.add(new MyInterface<Integer>() {
});
// 2. class extending interface
instances.add(new BaseImpl<Integer>());
// 3. class with pre-defined generic type
instances.add(new TypedImpl());
for (MyInterface<Integer> instance : instances) {
System.out.println("----------------------------------------------");
Class clazz = instance.getClass();
Type genericSuper = clazz.getGenericSuperclass();
Type[] genericInterfaces = clazz.getGenericInterfaces();
Class target = null;
System.out.println("class: " + clazz.getName());
System.out.println("generic super: " + genericSuper);
System.out.println("generic interfaces: " + Arrays.asList(genericInterfaces));
// attempt to 'extract' generic type
if (genericSuper instanceof ParameterizedType) {
target = getGeneric((ParameterizedType) genericSuper);
} else if (genericInterfaces.length > 0) {
for (Type genericInterface : genericInterfaces) {
if (genericInterface instanceof ParameterizedType) {
target = getGeneric((ParameterizedType) genericInterface);
if (null != target) {
break;
}
}
}
}
System.out.println("TARGET: " + target);
}
}
// attempt to get type argument
public static Class getGeneric(ParameterizedType type) {
if (MyInterface.class.isAssignableFrom((Class) type.getRawType())) {
Type typeArg = type.getActualTypeArguments()[0];
try {
return (Class) typeArg;
} catch (ClassCastException e) {
System.out.println("cast exception for '" + typeArg + "'");
}
}
return null;
}
}
import java.lang.reflect.ParameterizedType;
导入java.lang.reflect.Type;
导入java.util.array;
导入java.util.LinkedList;
公共班机{
公共接口MyInterface{
}
公共静态类BaseImpl实现MyInterface{
}
公共静态类TypedImpl扩展了BaseImpl{
}
公共静态void main(字符串[]args)引发异常{
LinkedList实例=新建LinkedList();
//1.来自接口的匿名类
添加(新的MyInterface(){
});
//2.类扩展接口
add(newbaseimpl());
//3.具有预定义泛型类型的类
add(newtypedimpl());
对于(MyInterface实例:实例){
System.out.println(“-------------------------------------------------------------”;
Class clazz=instance.getClass();
键入genericSuper=clazz.getGenericSuperclass();
类型[]genericInterfaces=clazz.getGenericInterfaces();
类目标=null;
System.out.println(“类:+clazz.getName());
System.out.println(“通用超级:“+genericSuper”);
System.out.println(“通用接口:“+Arrays.asList(GenericInterface));
//尝试“提取”泛型类型
if(参数化类型的genericSuper实例){
target=getGeneric((ParameteredType)genericSuper);
}else if(genericInterfaces.length>0){
for(类型genericInterface:genericInterface){
if(参数化类型的通用接口实例){
target=getGeneric((ParameteredType)genericInterface);
如果(空!=目标){
打破
}
}
}
}
System.out.println(“目标:+TARGET”);
}
}
//尝试获取类型参数
公共静态类getGeneric(ParameterizedType类型){
if(MyInterface.class.isAssignableFrom((class)type.getRawType())){
Type typeArg=Type.getActualTypeArguments()[0];
试一试{
返回(类)类型参数;
}catch(ClassCastException e){
System.out.println(“针对''+typeArg+''的强制转换异常”);
}
}
返回null;
}
}
其输出为:
----------------------------------------------
class: Main$1
generic super: class java.lang.Object
generic interfaces: [Main.Main$MyInterface<java.lang.Integer>]
TARGET: class java.lang.Integer
----------------------------------------------
class: Main$BaseImpl
generic super: class java.lang.Object
generic interfaces: [Main.Main$MyInterface<T>]
cast exception for 'T'
TARGET: null
----------------------------------------------
class: Main$TypedImpl
generic super: Main.Main$BaseImpl<java.lang.Integer>
generic interfaces: []
TARGET: class java.lang.Integer
----------------------------------------------
类别:主要$1
泛型超级类:java.lang.Object
通用接口:[Main.Main$MyInterface]
目标:类java.lang.Integer
----------------------------------------------
类别:Main$BaseImpl
泛型超级类:java.lang.Object
通用接口:[Main.Main$MyInterface]
“T”的强制转换例外
目标:空
----------------------------------------------
类别:Main$TypedImpl
通用超级:Main.Main$BaseImpl
通用接口:[]
目标:类java.lang.Integer
因此,我的目标是使target
变量的值为Integer.class
。对于匿名类(#1)和显式类型化实现(#3),我能够按预期找到目标。为什么它在这些实例中有效,而在#2(BaseImpl实例)中无效?有没有其他方法可以做到这一点?(我知道通过实现类的构造函数传递目标类
的常见解决方法,但是我对动态地这样做感兴趣)
我曾征询下列人士的意见:
Abel在案例1和案例3中,类型是类
Main$1
和Main$TypedImpl
上反射数据的一部分,因此您可以访问它
在案例2中,由于类型擦除,只有实例数据不包含任何类型信息。因此,您无法在此处访问泛型类型
进一步解释:
在运行时,系统无法区分BaseImpl i比如说BaseImpl s代码>,即由于类型擦除,两个变量i
和s
都属于BaseImpl
类型
相比之下,TypedImpl t已知code>的类型为TypedImpl
,使用反射可以提取extends
或implements
语句中提供的泛型类型
旁注,由于您正试图了解什么是可能的:
如果将BaseImpl
定义为BaseImpl实现MyInterface
,则可以从类BaseImpl
上的反射数据中提取T
的上限,即,您可以知道T
必须是Number
或子类型(或接口的实现)。(黑体字是我的)
使用Java泛型通常分为两种不同的方法之一
情况:
将类/接口声明为可参数化的
可参数化类。当您编写类或接口时,您可以
指定它应该是可参数化的
您可以创建对象列表,而不是创建对象列表
参数化java.util.List以创建所述字符串的列表
运行时检查可参数化类型本身时,如
如果是java.util.List,则无法知道类型是什么
参数化为。这很有意义,因为类型可以参数化
适用于同一应用程序中的所有类型。但是
声明使用参数化类型的方法或字段
可以在运行时看到什么类型的