【问题标题】:Does a subclass use parent constructor if one isn't defined in the subclass? [duplicate]如果子类中未定义父构造函数,子类是否使用父构造函数? [复制]
【发布时间】:2019-05-14 13:19:14
【问题描述】:

如果我有一个没有定义构造函数的子类,但在超类中定义了一个构造函数,当子类对象被实例化时,子类会使用该构造函数吗?

【问题讨论】:

  • 没有。只有子类的构造函数调用使用父构造函数。类本身没有。而且,是的,每个构造函数调用都会调用其父类的构造函数
  • 如果您没有自己显式创建构造函数,它将使用默认的Sub() { super(); }。这显然仅在父类具有无参数构造函数时才有效。如果没有,Java 将不编译你的程序。

标签: java class constructor


【解决方案1】:

如果子类中没有定义父构造函数,子类是否使用父构造函数?

这取决于您所说的“使用”是什么意思。如果您的意思是,子类的默认构造函数是否调用父构造函数,那么是的,它确实如此(更多下文)。如果你的意思是,是一个默认构造函数匹配父构造函数自动创建的任何参数,那么不,不是在一般情况下。

当您没有为子类声明任何构造函数时,会为您提供default constructor。总是这样

/*same access modifier as the class*/ Child() {
    super();
}

基类也有一个默认值,看起来一样,只是没有super();

因此,如果父类有一个无参数构造函数(显式地或通过默认),那么子类的默认构造函数将成功使用它。但是如果父类中定义了一个需要参数的构造函数,那么子类将无法编译,因为默认构造函数中的super()与父类中的构造函数不匹配。

比较一下,哪个有效:

public class Parent {
    public Parent() { // I could have left this off, since it's the default for a
    }                 // base class; it's here for emphasis
    public static void main(String[] args) {
        new Child();
    }
}

class Child extends Parent {
}

使用这个(在Parent 构造函数中添加了一个String 参数),但失败了:

public class Parent {
    public Parent(String s) {
    }
    public static void main(String[] args) {
        new Child();
    }
}

class Child extends Parent {
}

第二个失败:

类子扩展父{ ^ 必需:字符串 发现:没有参数 原因:实际参数列表和形式参数列表的长度不同 1 个错误

【讨论】:

    【解决方案2】:

    如果类中不写构造函数,其实是加了一个默认构造函数,从字节码中可以看出:

    class A {
    }
    

    将生成代码:

    class A extends Object {
        A() {
            super();
        }
    }
    

    每个构造函数都必须调用父类的构造函数作为第一条语句。 这里再次隐式调用super()

    class B extends A {
        B() {
            System.out.println();
        }
        B(int n) {
            System.out.println();
        }
    }
    

    将为

    生成代码
    class B extends A {
        B() {
            super(); // A()
            System.out.println();
        }
        B(int n) {
            super(); // A()
            System.out.println();
        }
    }
    

    这意味着可能会出现错误,即没有(重载的)构造函数可用于给定的参数类型。

    另外一点是,一般来说,super(); 声明毫无用处。

    【讨论】:

      【解决方案3】:

      假设您有一个扩展父级的空子类:

      public class TestChild extends TestParent{
      
      }
      

      父母看起来像:

      public class TestParent {
      
      private String testStr;
      
      public TestParent() {
          this.testStr = "I exist in the child class!";
      }
      
      public String getTestStr() {
          return testStr;
      }
      
      public void setTestStr(String testStr) {
          this.testStr = testStr;
      }
      }
      

      然后您在 main 中创建一个子对象并将其打印出来:

          TestChild test = new TestChild();
          System.out.println(test.getTestStr());
      

      结果会打印出来:

      I exist in the child class!
      

      这是因为子类会自动调用super 类的无参数构造函数。因此,您不需要在子类中明确需要构造函数,因为它会自动为您生成默认构造函数。

      【讨论】:

      • 您应该遵循 Java 命名约定:类名是用 PascalCase 编写的。
      • @MC Emperor 是的,我会改变它,很快就忘记了。谢谢!
      猜你喜欢
      • 2012-10-18
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多