我正在尝试根据类和参数创建一个类的实例。用于创建此类的方法如下所示:
@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,所以我认为没有理由不这样做。
这似乎是因为反射方法期望Player的类型而不是Mob的类型,但是Player不是唯一的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;
}
}
}
答案 0 :(得分:1)
getConstructor
method找不到构造函数,因为它只会找到参数类型的完全匹配。
要反映的构造函数是此Class对象所表示的类的公共构造函数,其形式参数类型与parameterTypes指定的类型匹配。
它不会像编译器那样工作,编译器会考虑将Player
扩展为Mob
的引用转换以匹配构造函数。
您需要找到合适的Constructor
。这是我能想到的最佳方式:
循环遍历Constructor
返回的所有getConstructors
。确定所有参数类型是否与您拥有的参数类型匹配,或者它们是否是您拥有的所有类型参数的超类。您可以使用Constructor
方法访问getParameterTypes()
的参数类型,该方法将访问与参数类型关联的Class
个对象。然后,您可以使用isInstance(params[i])
(或isAssignableFrom(params[i].getClass())
)。如果所有参数都匹配,则使用Constructor
。
这显然会变得混乱而且非常复杂,因为您正在完成编译器通常所做的工作 - 确定要调用的正确构造函数 - 但是出于这个目的,上述解决方案之一就足够了。即使您以上述方式获得了Constructor
个实例,您也应该能够找到Mob
Player
。