在arraylist中保存类名,并在Java中将参数发送到它们的方法

时间:2013-07-23 08:55:05

标签: java

我已经问了类似的事情,但我没有得到答案,所以我想在这里直截了当地提供尽可能多的细节。 基本上我有5个类,其中一个扩展 JFrame ,它是名为 TigBase 的主类,第二类扩展 JPanel ,它叫做 Cont 和第三个,第四个和第五个没有任何扩展,但它们具有相同的方法:

public void paintah(Graphics g){
       g.fillRect(20,20,20,20);

所以 JPanel 应该绘制它的图形。但我们也不知道这些类的名称。类的名称作为公共var

存储在 Cont 类中
public static ArrayList<String> classes = new ArrayList<String>();

所以我也有一个方法:

public void paintComponent(Graphics g){

是的,这些类的实际名称是 Cutscene0,Cutscene1,Menu2 我希望 Cont 类绘制他们的图形,但无法做到这一点。 如果我“知道”类的名称,我会这样做:

Cutscene0 cut = new Cutscene0();
public void paintComponent(Graphics g){
       super.paintComponent(g);
       Cutscene0 cut = new Cutscene0();
       cut.paintah(g);

但是我可能有更多相同类型的未知类,所以我需要将它们存储在arraylist中。我试过这个:

for(int i = 0; i<classes.size;i++){
    Class.forName(classes.get(i)).getMethod("paintah", Graphics.class).invoke(g);

但这给了我一个例外

java.lang.IllegalArgumentException: java.lang.ClassCastException@2c80fb85

所以是的,我真的需要让它成功,我整天都在研究如何做到这一点并尝试不同的东西,但他们只是没有工作..希望你能帮忙!

2 个答案:

答案 0 :(得分:3)

这是Method.invoke()的javadoc:

public Object invoke(Object obj,
                     Object... args)
              throws IllegalAccessException,
                     IllegalArgumentException,
                     InvocationTargetException
  

使用指定的参数调用此Method对象表示的基础方法在指定对象上。

(强调我的)。

您的“传统”方法调用看起来像

Cutscene0 cut = new Cutscene0();
cut.paintah(g);

要使用反射做同样的事情,你必须

  • 通过调用no-arg构造函数
  • 创建类的实例
  • 在此实例上调用方法

所以你会有像

这样的东西
Class<?> clazz = Class.forName(classes.get(i));
Object cut = clazz.newInstance(); // no-arg constructor
Method method = clazz.getMethod("paintah", Graphics.class);
method.invoke(cut, g); // invoke the method on cut, with g as parameter

那就是说,你没有说明为什么你不知道类名。我觉得适当的OO模式,如工厂,可以使事情更清晰。至少,您的所有类都可以实现相同的接口Painter,然后您就可以执行

Class<?> clazz = Class.forName(classes.get(i));
Painter cut = (Painter) clazz.newInstance(); // no-arg constructor
cut.paintah(g);

答案 1 :(得分:0)

关于您的例外:来自Method javadoc

  

方法允许在匹配时进行扩展转换   用底层方法正式调用的实际参数   参数,但如果发生IllegalArgumentException,则会引发narrowing conversion

但无论如何我认为你应该避免反思,如果你可以使用interface而不是string classname:

interface Paintable {
  public void paintah(Graphics g)
}

public static ArrayList<Paintable> ps = new ArrayList<Paintable>();

for(int i = 0; i<ps.size;i++){
    ps.get(i).paintah(g)
}