Java 通过反射从实例获取泛型类型

Java 通过反射从实例获取泛型类型,java,generics,Java,Generics,让我从一个可能重复的免责声明开始。。。我确实试着仔细研究了一些关于这个话题的问题,但它们并不代表我对我想要实现的目标的挑战。所以请宽容我,帮助我解决问题 以下是我的情况: 我有一个接口(在命令模式中),如下所示,我需要为其实现 public interface IIntelligentAction<E> { /** * Set dynamic variable for this action. */ public void setDynamicO

让我从一个可能重复的免责声明开始。。。我确实试着仔细研究了一些关于这个话题的问题,但它们并不代表我对我想要实现的目标的挑战。所以请宽容我,帮助我解决问题

以下是我的情况: 我有一个接口(在命令模式中),如下所示,我需要为其实现

public interface IIntelligentAction<E> {
    /**
     * Set dynamic variable for this action.
     */
     public void setDynamicOperand(Callable<?> getter);

    /*
     * Set validating operand for this action.
     */
     public void setValidatingOperand(Callable<?> getter);

    /*
     * The implementation must check if the operands (dynamic and validating) are 
     * compatible with each other for this action. 
     */
     public boolean areOperandsCompatible();

    /*
     * Execute this action.
     * <p> The implementation must check for both operands being assigned and are
     * compatible with each other, before allowing the action to execute.
     */
     public void execute();

}
公共接口智能操作{
/**
*为此操作设置动态变量。
*/
公共void setDynamicOperand(可调用getter);
/*
*设置此操作的验证操作数。
*/
public void setValidatingOperand(可调用的getter);
/*
*实现必须检查操作数(动态和验证)是否正确
*对于此操作,彼此兼容。
*/
公共布尔运算对象是可兼容的();
/*
*执行此操作。
*实现必须检查两个被赋值的操作数,并且
*相互兼容,然后才允许执行操作。
*/
公共无效执行();
}
界面的设计是有意的,我理解其基本原理(例如,
Date
Calendar
在语义上兼容,但不兼容类型)


现在我关心的是
操作数兼容()
方法。可以看出,该方法接受参数化的
可调用的
,因此通过反射,我将始终看到
可调用的
,但不会看到它将返回的类型。如何访问从setter方法获得的泛型实例的参数化类型?

我最终实现此问题解决方案的方式他与下列人士保持联系:

public Class<?> getGenericsTypeDeclared(Object any) {
        List<Type> classScope = new ArrayList<Type>();
        classScope.add(any.getClass());
        classScope.add(any.getClass().getGenericSuperclass());

        for (Type type : any.getClass().getGenericInterfaces())
            classScope.add(type);

        Class<?> genericType = null;

        for (Type type : classScope) {
            try {
                genericType = (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[0];
            } catch (ClassCastException e) {
                if (logging != null)
                    logging.warn("Ignoring non-generic type: " + type);
            } catch (ArrayIndexOutOfBoundsException e) {
                if (logging != null)
                    logging.warn("Oddly Generic type without parameters. Found: " + type);
            }

            if (genericType != null) {
                return genericType.getClass();
            }
        }

        return null;
    }
公共类getGenericsTypeDeclared(对象任意){
List classScope=new ArrayList();
添加(any.getClass());
添加(any.getClass().getGenericSuperclass());
for(类型:any.getClass().getGenericInterfaces())
添加(类型);
类genericType=null;
for(类型:classScope){
试一试{
genericType=(类)((ParameteredType)类型).getActualTypeArguments()[0];
}catch(ClassCastException e){
if(记录!=null)
logging.warn(“忽略非泛型类型:“+type”);
}捕获(阵列索引边界外异常e){
if(记录!=null)
logging.warn(“没有参数的奇怪泛型类型。找到:“+type”);
}
if(genericType!=null){
返回genericType.getClass();
}
}
返回null;
}

该方法使用本机java,因此不需要任何第三方库。希望它能帮助其他搜索类似需求的人。

我认为这是不可能的,因为类型擦除。您可以将类与
Callable
一起传递给该方法,然后在需要时在运行时使用它。您的
Callable
没有任何类型parameter,它们使用通配符类型。不清楚您要检查什么。也不清楚
在哪里起作用。您的意思是要执行
可调用
?您可能可以使用前面提到的构造,但只有当您有一个提供具体类型参数的子类,如
类MyCallable implem时,这才有效ents可调用{…}
。如果有
类,MyCallable实现可调用{…}
那么反射就不起作用了。如果你不明白反射什么时候起作用/为什么起作用,那么传递一个
比任何其他选项都要容易得多。你找到解决方案了吗?我有一个类似的要求来比较泛型类型的兼容性,例如
日期
日历
在语义上是一致的在Java中不兼容但类型不兼容。您的解决方案将对我有很大帮助。