【问题标题】:Constructor of a derived class (Java)派生类的构造函数 (Java)
【发布时间】:2014-09-28 17:20:59
【问题描述】:

我是 Java 新手,即将提出一个基本问题。希望你们能帮助我。假设我有一个基类 Super 和一个派生类 Sub,继承自 Super 类如下:

public class TestSuperSub {
  public static void main(String[] args) {
    Super ou = new Sub(5,10);
  }
}

class Super {
  Super() {
    System.out.println("Super()");
  }

  Super(int x, int y) {
    System.out.println("Super(int, int)");
  }
}

class Sub extends Super {
   public Sub(int x, int y) {
      System.out.println("Sub(int, int)");
   }
}

输出是

Super()
Sub(int, int)

我知道,您调用 Sub::Sub(int,int) ,因此打印了 Sub(int, int)。但是为什么 Super() 打印出来,因为 Super::Super() 从来没有被调用过?

谁能给我解释一下。 非常感谢! 干杯

【问题讨论】:

  • 如果此问题得到解决,请选择一个答案以标记为已接受(绿色复选标记),您也可以为有帮助的答案投票。

标签: java oop inheritance constructor


【解决方案1】:

默认情况下,Java 将调用超类的无参数构造函数除非您显式调用另一个构造函数。如果要调用Super(int, int),必须显式调用:

public Sub(int x, int y) {
  super(x, y);
  System.out.println("Sub(int, int)");
}

【讨论】:

    【解决方案2】:

    但是为什么 Super() 打印出来,因为 Super::Super() 从来没有被调用过?

    它有,因为您的 Sub 构造函数正在隐式调用它。就像你写的那样:

    public Sub(int x, int y) {
       super();
       System.out.println("Sub(int, int)");
    }
    

    来自section 8.8.7 of the JLS

    构造函数主体的第一条语句可能是对同一类或直接超类的另一个构造函数的显式调用(第 8.8.7.1 节)。

    ...

    构造函数通过一系列一个或多个涉及此的显式构造函数调用直接或间接调用自身是编译时错误。

    如果构造函数体不是以显式构造函数调用开始并且被声明的构造函数不是原始类 Object 的一部分,则构造函数体隐式以超类构造函数调用“super();”开始,调用不带参数的直接超类的构造函数。

    如果要调用不同的超类构造函数,则需要隐式执行。当您调用子类构造函数时,它将总是通过继承层次结构向上工作,在子类构造函数之前执行超类构造函数的主体......事实上,即使是子类中的字段初始化器也只是在超类构造函数之后运行。

    【讨论】:

      【解决方案3】:

      它是 Java 中非常基本的基本概念。它是 super 关键字和 constructor chainingma​​gic

      浏览这些链接。希望这能帮助你理解这个概念。

      http://docstore.mik.ua/orelly/java-ent/jnut/ch03_04.htm

      http://docs.oracle.com/javase/tutorial/java/IandI/super.html

      【讨论】:

        【解决方案4】:

        默认在子类的构造函数中 第一行是调用基类默认构造函数(隐式),如果没有提到构造函数是 **

        超级();

        ** 如果你写

        超级(x,y);

        然后会调用其他构造函数

        注意:构造函数的第一行是调用基类构造函数。 如果没有超类,则调用 Object 类的构造函数

        【讨论】:

          【解决方案5】:

          当您实例化一个类时,所有超类层次结构也必须被实例化,这将通过每个类自动可用的空构造函数来完成。

          以下代码

          public class Superclassing {
          
              public static void main(String[] args) {
          
                  new C();
              }
          
              Superclassing() {   System.out.println("super");    }
          }
          
          class A extends Superclassing {
          
              A() {   System.out.println("A");    }
          }
          
          class B extends A {
          
              B() {   System.out.println("B");    }
          }
          
          class C extends B {
          
              C() {   System.out.println("C");    }
          }
          

          输出

          super
          A
          B
          C
          

          它是按照 Skeet 的回答和此处所述的设计完成的(奇怪的是,它在 8.8.7 中解释之前就提到过):

          JLS 8.8.3. Constructor Modifiers

          缺少 native 构造函数是一种任意的语言设计选择 这使得 Java 虚拟机的实现变得容易 验证 超类构造函数是否总是被正确调用 在对象创建期间

          (强调我的。)

          【讨论】:

            【解决方案6】:
            class A{
            A(){
                System.out.println("no-arg constructor in A");
            }
            
            A(int a){
                System.out.println("parameterized constructor in A");
            }
            }
            
            class B extends A{
            B(){
            
                System.out.println("no-arg constructor in B");
            }
            
            B(int b){
                        //by default during compilation super() keyword will be added in first line of this constructor
                System.out.println("paramterized constructor in B");
            }
            
            }
            public class TestDemo {
            public static void main(String[] args) {
                B aVar = new B(10); 
                aVar = new B();
            
            }
            
            }
            
            Output:
              // output for first object i.e, new B(10)
               no-arg constructor in A
               paramterized constructor in B
              //output for second object i.e, new B()
               no-arg constructor in A
               no-arg constructor in B
            

            编译器会根据你在main方法中创建的对象,默认添加一个super()关键字。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-07-19
              • 2020-02-28
              • 2011-12-29
              • 2018-07-21
              • 2018-07-16
              • 2012-11-06
              • 1970-01-01
              • 2016-10-06
              相关资源
              最近更新 更多