使用反射调用方法时的通用返回类型

时间:2013-12-20 13:51:16

标签: java reflection

首先,请阅读以下代码。

我想调用SuperClass的invoke方法,而不必将返回值强制转换为相应的类型。 问题是SuperClass实现位于一个项目中,SuperClassImpl1和2位于另一个项目中。

在运行时,它们位于不同的类加载器中,即ClassLoader 1知道SuperClass但不知道SuperclassImpl1。我有一个“SuperClassLoader”,它给ClassLoader 1一个类对象,例如SuperClassImpl2,但我只能将它用作SuperClass对象。

现在我的代码看起来像下面的代码,我必须将其转换为例如如果我知道我给invoke的方法名返回一个Map,那就是Map。

我想要的是,取决于methodName给出的方法的返回类型,invoke方法的返回类型应该相应地改变。

E.g。 invoke("getMyMap")应该返回一张地图。请注意,我不想要这个:

Map m = invoke("getMyMap");

m.get(...);

我想要这个:

invoke("getMyMap").get(...);

有可能吗?

public abstract class SuperClass(){

    public Object invoke(String methodName){
        Method method = this.getClass().getDeclaredMethod(methodName);

        return method.invoke(this);
    }
}


public class SuperClassImpl1() extends SuperClass{

    Map<String,String> myMap;
    public SuperClassImpl1(){
        myMap = new HashMap<String,String>();
    }

    public Map<String,String> getMyMap(){
        return myMap;
    }
}

public class SuperClassImpl2() extends SuperClass{

    List<String> myList;
    public SuperClassImpl2(){
        myList = new ArrayList<String>();
    }

    public ArrayList<String> getMyList(){
        return myList;
    }
}

public class MainClass(){
    public static void main(String[] args){
        SuperClass mySuperClass1 = new SuperClassImpl1();
        SuperClass mySuperClass2 = new SuperClassImpl2();

        System.out.println("Something in my map: "+mySuperClass1.invoke("getMyMap").get("Some value"));

        // something similar using mySuperClass2 here...
    }
}

3 个答案:

答案 0 :(得分:2)

问题在于,在invoke()的定义中,返回类型始终是一个对象。这就是事情的方式。(documentation

如果你想使用反射,你必须在某些时候使用转换。您可以创建一个包装方法来为您进行转换,但是没有解决它。

我开始工作的方式是这样的:

System.out.println("Something in my map: "+((Map<?, ?>) mySuperClass1.invoke("getMyMap")).get("Some value"));

答案 1 :(得分:0)

您不能这样做,因为在编译时检查泛型类型,并且在运行时才知道您调用的方法的实际返回类型。

Map m = invoke("getMyMap"); // checked at compile time

return method.invoke(this); // resolved at run time

答案 2 :(得分:0)

方法的返回类型不能依赖于传递给它的String,因为类型在编译时解析,而参数只在运行时知道。

但是,您可以在类中添加参数。

public abstract class SuperClass<T> {

    public T invoke(String methodName){
        Method method = this.getClass().getDeclaredMethod(methodName);

        return (T) method.invoke(this);
    }
}


public class SuperClassImpl1() extends SuperClass<Map<String, String>> {
    ...
}

public class MainClass(){
    public static void main(String[] args){
        SuperClass<Map<String, String>> mySuperClass1 = new SuperClassImpl1();
        SuperClass<ArrayList<String>> mySuperClass2 = new SuperClassImpl2();

        System.out.println("Something in my map: "+mySuperClass1.invoke("getMyMap").get("Some value"));

        // something similar using mySuperClass2 here...
    }
}