2013-12-20 73 views
0

首先,阅读下面的代码。使用反射调用方法时的通用返回类型

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

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

现在我的代码看起来像下面的代码,我必须将它转换为一个Map如果我知道我给调用的方法名返回一个Map。

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

E.g. invoke("getMyMap")应该返回一个Map。请注意,我不希望这样的:

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... 
    } 
} 

回答

2

问题是,在invoke()的定义中,返回类型始终是一个对象。 (documentation

如果你想使用反射,你将不得不在某个时刻使用反射。你可以创建一个包装方法来为你进行演员制作,但是没有办法绕过它。

我得到了它的工作方式是这样的:

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

这与我已有的相似,似乎我必须坚持这一点。 –

0

你不能这样做,因为泛型是在编译期进行检查,并调用不知道,直到运行时的方法的实际返回类型。

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

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

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

但是,您可以为您的课程添加参数。

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... 
    } 
} 
+0

是的,如果超类的实施将做具体的事情,这会工作。不幸的是,这并不适合我,因为这些SuperClass实现中的一个可以有任何类型的方法和数据结构。 –