简体   繁体   English

如何从具有泛型类型的抽象类中调用方法(使用Java反射)

[英]How To invoke a Method (with java reflection) from abstract class with generic type

The Classes simplified: 简化的类:

public abstract class AbstractFieldGroupBind<T> {

    public Class<T> beanClass;
    public BeanFieldGroup<T> binder;

    public void initGroupBinder(Object vaadinComponent){
        binder = new BeanFieldGroup<T>(beanClass);
        binder.bindMemberFields(vaadinComponent);
}


public class StammdataEditFGB extends AbstractFieldGroupBind<Cinema> {

    public void pushItem(Item item) {
        binder.setItemDataSource(item);
    }

}

Now I try to invoke the method "initGroupBinder" by a composer Class. 现在,我尝试通过作曲家类调用方法“ initGroupBinder”。 If invoke the method like: 如果调用如下方法:

Method method = theFGBClass.getClass().getSuperclass().getDeclaredMethod("initGroupBinder", Object.class);
method.invoke(....)

If will call the class but without the Type . 如果将调用该类但没有Type。 It will not work like this. 它不会像这样工作。

I also can get the generic superclass and there I find the type set in extends. 我也可以得到通用超类,然后在extends中找到类型集。 But how to bring it together to invoke the method like: 但是如何将其组合在一起以调用方法,例如:

public void initGroupBinder(Object vaadinComponent){
    binder = new BeanFieldGroup<Cinema>(Cinema.class);
    binder.bindMemberFields(vaadinComponent);
}

ADD: I get the class "StammdataEditFGB" in the composer via Spring by context.getBean(). 添加:我通过context.getBean()通过Spring在作曲家中获得了“ StammdataEditFGB”类。 This construct run in a Spring Context. 该构造在Spring Context中运行。 So also a solution with Spring's ReflectionUtils is very welcome. 因此,非常欢迎使用Spring的ReflectionUtils解决方案。

Found the solution! 找到了解决方案! There 2 Problems. 有2个问题。

1. getDeclaratedMedothod will not find methods there are in extented Classes. 1. getDeclaratedMedothod不会在扩展类中找到方法。 By using getMethod you will get methods (methods must be public) in Abstract Classes. 通过使用getMethod您将在Abstract Classes中获得方法(方法必须是公共的)。
Here a small example to show. 这里有一个小例子来展示。

 public class Test {

    public abstract class AbstractPerson{
        public void callMe(){
            System.out.println("Method callMe() in AbstractPerson");
        }
    }

    public class Person extends AbstractPerson{}

    public static void main(String[] args) {

        Test test = new Test();
        Person person = test.new Person();

        try {
            Method method;
            System.out.println("### Use getMethod");
            method = person.getClass().getMethod("callMe", (Class<?>[]) null);
            method.invoke(person, null);
            System.out.println("### Use getDeclaredMethod");
            method = person.getClass().getDeclaredMethod("callMe", (Class<?>[]) null);
            method.invoke(person, null);
        } 
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Console: 安慰:

### Use getMethod
Method callMe() in AbstractPerson
### Use getDeclaredMethod
java.lang.NoSuchMethodException: Test$Person.callMe()
    at java.lang.Class.getDeclaredMethod(Class.java:2004)
    at Test.main(Test.java:27)

After solving that issue there has been the next one with generic type T. 解决该问题后,出现了下一个通用类型T。

2. The BeanFieldGroup could not be initialized like I did. 2.无法像我一样初始化BeanFieldGroup Of course the beanClass is Null. 当然, beanClass为Null。
Here the solution with setting the beanClass for BeanFieldGroup properly: 这里是正确设置BeanFieldGroup的beanClass的解决方案:

public abstract class AbstractFieldGroupBind<T> implements IFieldGroupBind<T>{

    protected BeanFieldGroup<T> binder;

    @Override
    public void initGroupBinder(Object view){
        binder = new BeanFieldGroup<T>(getClassForT());
        binder.bindMemberFields(view);
    }

    @Override
    public void pushItem(T item) {
        binder.setItemDataSource(item);
    }

    @Override
    public T getItem() {
        return binder.getItemDataSource().getBean();
    }

    @SuppressWarnings("unchecked")
    private Class<T> getClassForT(){
        Type superClazz = this.getClass().getGenericSuperclass();
        Type tClazz = ((ParameterizedType)superClazz).getActualTypeArguments()[0];
        return (Class<T>) tClazz;
    }
}

Now it works! 现在可以了!

When you instantiate an object of class StammdataEditFGB , you are already passing the type information to the super class. 当实例化StammdataEditFGB类的对象时,您已经将类型信息传递给了超类。 So, when you call theFGBClass.getClass().getSuperClass() , you will get a AbstractFieldGroupBind class that handles Cinema objects. 因此,当您调用theFGBClass.getClass().getSuperClass() ,将获得一个处理Cinema对象的AbstractFieldGroupBind类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM