我试图基于类和参数创建一个类的实例。用于创建此类的方法如下所示:

@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);

其中thisPlayer类的实例,该类扩展了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实例,您也应该能够找到采用MobPlayer

09-08 08:26