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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当参数是构造函数的参数声明类型的子类时,反射找不到构造函数相关的知识,希望对你有一定的参考价值。

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

目前的代码如下:

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.beans包有类StatementExpression,可以使用子类型规则执行必要的查找:

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

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

另一答案

我选择使用的解决方案是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);
    }
}

非常简单的代码很好

以上是关于当参数是构造函数的参数声明类型的子类时,反射找不到构造函数的主要内容,如果未能解决你的问题,请参考以下文章

注入 dbContext 时返回“找不到与给定参数匹配的构造函数”

com.din.OSS 中构造函数的参数 0 需要找不到类型为“java.lang.String”的 bean

基类和子类函数名相同且参数类型一样,基类函数如何被覆盖,还存在吗?存在何处?请详细回答,谢谢~~~~

如何解决此问题:LoginController 中构造函数的参数 0 需要找不到类型为“OktaOAuth2Properties”的 bean

Flutter 6种构造函数详解

子类调用父类的构造函数