当参数是构造函数的参数声明类型的子类时,反射找不到构造函数

问题描述 投票:3回答:2

我正在使用反射来实例化特定需求的类。

目前的代码如下:

public final <T> T instanciate(Class<? extends T> a_clazz, Object... args) {

    // Other stuff when no arg...

    Class<?>[] l_argsClasses = getClassesFromObjects(args);
    Constructor<?> constructor = a_clazz.getConstructor(l_argsClasses);
    constructor.newInstance(args)
}

不幸的是,我读到,当给定的参数与构造函数声明中的类型不完全相同时,它将不起作用。

所以当我给出一个子类时,找不到构造函数,我得到一个NoSuchMethodException。

似乎这里没有处理多态的机制。

示例:

public class A {

}

public class B extends A {

}

public class Foo extends A {
    public Foo(A a) {

    }
}

将工作 :

instanciate(Foo.class, new A());  // because Foo(A a)

不会工作:

instanciate(Foo.class, new B());  // because Foo(B b) does't exists

您有解决此问题的任何解决方案吗?

谢谢

java reflection polymorphism
2个回答
2
投票

java.beans包有类StatementExpression,可以使用子类型规则执行必要的查找:

Expression e = new Expression(Foo.class, "new", new Object[]{ new B() });
Foo foo = (Foo)e.getValue();

execute method的文档描述了用于调用构造函数的特殊伪方法名称"new"


0
投票

我选择使用的解决方案是apache.commons.lang.reflect提供的方法

它提供了两个不同的版本:

  • 需要完全匹配参数类型:invokeExact Constructor()
  • 一个匹配参数类型通过赋值兼容性:invokeConstructor()

我已经进行了简单的测试并且它正在运行。所以我正在使用它。

结果如下:

public final <T> T instanciate(Class<? extends T> clazz, Object... args) {
    try {
        return clazz.cast(ConstructorUtils.invokeConstructor(clazz, args));
    } catch (Exception e) {
        throw new RuntimeException("Failed to instanciate Object", e);
    }
}

非常简单的代码很好

© www.soinside.com 2019 - 2024. All rights reserved.