方法存在时抛出NoSuchMethodException

时间:2015-06-09 19:19:26

标签: java

我正在尝试根据类和参数创建一个类的实例。用于创建此类的方法如下所示:

@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,所以我认为没有理由不这样做。

这似乎是因为反射方法期望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;
        }
    }
}

1 个答案:

答案 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