我试图基于类和参数创建一个类的实例。用于创建此类的方法如下所示:
@SuppressWarnings("unchecked")
public Plugin instantiatePlugin(Class clazz, Object... params) {
try {
Class plugin = pluginClasses.get(clazz);
if (params.length > 0) {
Class[] parameterTypes = new Class[params.length];
for (int i = 0; i < parameterTypes.length; i++) {
parameterTypes[i] = params[i].getClass();
}
return (Plugin)plugin.getDeclaredConstructor(parameterTypes).newInstance(params);
} else {
return (Plugin)plugin.newInstance();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
我收到的错误如下:
java.lang.NoSuchMethodException:plugin.movement.WalkRunPlugin。(com.rr.server.entity.mob.player.Player)
尝试调用已声明的构造函数时。这是我要传递给方法的内容:
instantiatePlugin(MovementPlugin.class, this);
其中
this
是Player
类的实例,该类扩展了Mob
。这是我的
only
示例中的WalkRunPlugin
构造函数:public WalkRunPlugin(Mob mob) {
this.mob = mob;
}
考虑到Mob是抽象的,而Player扩展了Mob,Player是Mob,因此我认为没有理由不起作用。
这似乎是因为反射方法期望播放器的类型而不是Mob的类型,但是播放器不是唯一的Mob。因此,我需要找到一种在此方法中接受超类的子类的方法。
提示?
编译示例:
public class Example {
public static void main(String[] args) {
new Example();
}
private Example() {
try {
Class clazz = Plugin.class;
clazz.getDeclaredConstructor(Player.class).newInstance(new Player());
} catch (Exception e) {
e.printStackTrace();
}
}
public static abstract class Mob {
}
public static class Player extends Mob {
}
public static class Plugin {
Mob m;
Plugin(Mob m) {
this.m = m;
}
}
}
最佳答案
getConstructor
method不会找到构造函数,因为它只会找到参数类型的完全匹配项。
要反映的构造函数是此Class对象表示的类的公共构造函数,其正式参数类型与parameterTypes指定的类型相匹配。
它不会像编译器那样工作,后者将考虑将Player
扩展为Mob
的可能的参考转换以匹配构造函数。
您将需要找到正确的Constructor
。这是我能想到的最好方法:
循环遍历Constructor
返回的所有getConstructors
。确定所有参数类型是否与您拥有的参数类型匹配,或者它们是否为您拥有的所有参数类型的超类。您可以使用Constructor
方法访问getParameterTypes()
的参数类型,该方法将访问与参数类型关联的Class
对象。然后,您可以使用isInstance(params[i])
(或isAssignableFrom(params[i].getClass())
)。如果所有参数都匹配,则使用该Constructor
。
这显然会变得混乱并且非常复杂,因为您正在执行编译器通常会做的工作-确定要调用的正确构造函数-但为此,上述解决方案之一就足够了。通过以上方式,即使您已获得Constructor
实例,您也应该能够找到采用Mob
的Player
。