我已经问了类似的事情,但我没有得到答案,所以我想在这里直截了当地提供尽可能多的细节。 基本上我有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
所以是的,我真的需要让它成功,我整天都在研究如何做到这一点并尝试不同的东西,但他们只是没有工作..希望你能帮忙!
答案 0 :(得分:3)
这是Method.invoke()
的javadoc:
public Object invoke(Object obj,
Object... args)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
使用指定的参数调用此Method对象表示的基础方法在指定对象上。
(强调我的)。
您的“传统”方法调用看起来像
Cutscene0 cut = new Cutscene0();
cut.paintah(g);
要使用反射做同样的事情,你必须
所以你会有像
这样的东西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)
}