【问题标题】:"Could not resolve matching constructor" error when passing in constructor-arg for child class为子类传递构造函数参数时出现“无法解析匹配的构造函数”错误
【发布时间】:2014-02-05 16:51:58
【问题描述】:

我有以下课程:

public abstract class ParentClass
{
    public ParentClass()
    {
        throw new RuntimeException("An ID must be specified.");
    }

    public ParentClass(String id)
    {
        this(id, DEFUALT_ARG_VALUE);
    }

    public ParentClass(String id, int anotherArg)
    {
        this.id = id;
        //stuff with anotherArg
    }

    public abstract void doInstanceStuff();
}

public class ChildClass extends ParentClass
{
    @Override
    public void doInstanceStuff()
    {
        //....
    }
}

在我的应用程序上下文中,我有这个:

<bean id="myChildInstance" class="com.foo.bar.ChildClass " scope="singleton">
    <constructor-arg value="myId" />
</bean>

问题是服务器启动时出现以下错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ivpluginHealthCheckTest' defined in ServletContext resource [/WEB-INF/spring/root-context.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)

看到错误,我尝试添加不同的属性,但没有成功。我最终得到了这样的结果:

<bean id="myChildInstance" class="com.foo.bar.ChildClass " scope="singleton">
    <constructor-arg value="myId" index="0" type="java.lang.String" name="id" />
</bean>

我仍然遇到同样的错误。

我尝试将相同的构造函数添加到我的子类中,并且只需调用 super() 并为每个类添加适当的参数,这似乎可以解决问题。但是,我不想在我的所有子实例中添加相同的构造函数,并且必须使用父类来维护它们。

Spring 在调用继承的构造函数来实例化类时遇到问题是否有某些原因?我可以做些什么来完成这项工作吗?

【问题讨论】:

    标签: java spring inheritance constructor


    【解决方案1】:

    调用继承的构造函数来实例化类?

    构造函数永远不会被继承,这没有任何意义。构造函数只是初始化该特定类中的状态。你不能指望Parent 的构造函数来初始化Child 类的状态。这只是 Child 类中构造函数的工作。

    所以,不,你不能做你想做的事。这不是 Spring 的问题。这是非常基本的。

    【讨论】:

    • 这并不像你说的那么明显。我们假设所有方法都是通过从类扩展继承的,并且构造函数定义在技术上是一种方法,所以我可以看到人们认为可以继承构造函数方法。
    • @MohammadS。唔。是啊,你说得对。删除了我回答的那部分。
    • 你说的很有道理。有一次,我只在父类中留下了默认构造函数,在子类中什么都没有,它确实抛出了异常。我想这是因为默认构造函数隐含了一个隐含的超级调用(除非我也误解了)。这让我觉得其他的也被继承了。
    • @dnc253 是的,如果您不提供任何构造函数,编译器将始终添加默认构造函数。
    • @dnc253 你是对的。子类中的隐式默认构造函数隐式调用super()。因此调用了超类的默认构造函数。
    【解决方案2】:

    简答:Java 中不继承构造函数。

    来自JLS

    Constructor declarations are not members. They are never inherited and therefore are not subject to hiding or overriding. 
    

    这意味着您必须声明每个子类所需的构造函数并调用相应的超级构造函数。即使它具有相同的签名,也不能算作覆盖。

    【讨论】:

      【解决方案3】:

      如果你没有在你的子类中提供构造函数,编译器会插入一个无参数构造函数并将第一行添加为对超级无参数构造函数的调用 所以你的代码变成了:-

      public class ChildClass extends ParentClass {
      
              public ChildClass() {
                  super();
              }
          }
      

      显然,你抛出了一个可能导致问题的空指针异常。我建议你添加一个构造函数并调用带有字符串参数的超级构造函数:-

      public class ChildClass extends ParentClass {
              public ChildClass(String id) {
                  super(id);
              }
      
              @Override
              public void doInstanceStuff() {
                  // ....
              }
          }
      

      这应该可以解决你所有的问题...

      注意:- 如果您添加参数构造函数,编译器不会为您添加默认构造函数。

      现在您的 bean 将正确初始化,因为它将调用字符串参数构造函数。目前,编译器正在为您提供一个默认的无参数构造函数,该构造函数反过来调用您的无参数父类构造函数并引发空指针异常..

      【讨论】:

        猜你喜欢
        • 2017-05-01
        • 2015-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多