为什么构造函数中不能同时使用this()和super()?

41

为什么构造函数中不能同时使用this()super()?

为什么要这样规定呢?


5
如何调用重载构造函数中的 super 和 this?如何在重载构造函数中同时调用 super 和 this?Stack Overflow 上有一个关于此问题的讨论:https://dev59.com/W2w05IYBdhLWcg3w41wp。 - Ciro Santilli OurBigBook.com
11个回答

48

this(...)会调用同一类中的另一个构造函数,而super()会调用超类的构造函数。如果在构造函数中没有使用super(),编译器将隐式地添加一个。

因此,如果两者都允许,则可能会调用super构造函数两次。

示例(不要在参数中寻找意义):

class A {
  public A() {
    this( false );
  }

  public A(boolean someFlag) {
  }
}

class B extends A {
  public B() {
    super();
  }

  public B( boolean someFlag ) {
    super( someFlag );
  }

  public B ( int someNumber ) {
    this(); //
  }
} 

现在,如果你调用 new B(5) ,将会调用以下构造函数:

     this( false);
A() ---------------> A(false)
^
|
| super(); 
|
|     this();
B() <--------------- B(5)  <--- you start here

更新:

如果你能够使用this()super(),你可能会得到像这样的东西:

(注意: 这只是为了展示可能出现的问题,如果您被允许这样做的话 - 幸运的是您不能这样做)

     this( false);
A() ---------------> A(false)
^                    ^
|                    |
| super();           | super( true ); <--- Problem: should the parameter be true or false? 
|                    |
|     this();        |
B() <--------------- B(5)  <--- you start here

正如您所看到的,您将遇到一个问题,即可以使用不同的参数调用A(boolean)构造函数,现在您必须决定使用哪个。此外,其他构造函数(A()B())可能包含代码,现在可能不会正确调用(即顺序不对等),因为对super(true)的调用将规避它们,而对this()不会。


14

super()this() 之间有区别。

super() - 调用基类构造函数,而
this() - 调用当前类构造函数。

两者均为构造函数调用。
构造函数调用必须始终是第一条语句。 所以你只能将 super()this() 作为第一条语句之一。


1
基本上一次只能使用一个语句,"我们不能有两个语句作为第一个语句"是什么意思,这没有意义。 - Balaswamy Vaddeman

4
  • 在构造函数链接中,我们使用this()关键字来访问同一类的构造函数。
  • 在继承中,当我们想要访问直接父类的构造函数时,我们使用super()关键字。

两者都必须在你使用的构造函数的第一行中声明。这就是为什么我们不能在单个构造函数中同时使用两者的原因,因为你只能在第一行中写一个东西。


4

this()super()都是构造函数调用,构造函数调用必须是构造函数中第一个(且仅为第一个)调用。否则,在实例化单个对象时将会多次调用Object构造函数。


2

构造函数中不能同时使用this()和super()。

this()用于调用同一类的默认构造函数,应该是构造函数中的第一条语句。

super()用于调用基类的默认构造函数,应该是构造函数中的第一条语句。

因此,this()和super()都用于构造函数调用,但都希望在首位执行。这就是为什么会显示编译器错误:

错误:调用this必须是构造函数中的第一条语句 this(); 或者

错误:调用super必须是构造函数中的第一条语句 super();


2

因为这没有意义。构造函数必须调用this()super()(隐式或显式)。this()调用另一个构造函数,该构造函数必须像以前一样调用this()super()等等。调用this()super()的构造函数最终会调用super()两次。


1
因为如果在构造函数中同时使用this()super(),会导致编译时错误。因为this()super()必须是第一个可执行的语句。如果您首先编写this(),那么super()将成为第二个语句,反之亦然。这就是为什么我们不能同时使用this()super()的原因。

0

比较下面的例子。FirstChild类在两个构造函数中设置实例变量名称,因为第一个构造函数调用第二个构造函数被排除了,需要调用super()。

在SecondChild类中引入了第三个私有构造函数,它接受2个参数-第一个传递给supper(),第二个用于设置名称。前两个构造函数都调用第三个构造函数。Super()仅被调用一次,实例变量也仅在一个构造函数中设置。代码产生相同的结果,无需在同一个构造函数中调用super()和this()。

class FirstChild extends ConstructorTest{
    private String name = null;
    public FirstChild(){
        super("super text 1");
        //this("Unknown"); //UNCOMMENTED DOES NOT COMPILE
        name = "Unknown";
    }
    public FirstChild(String name){
        super("super text 2");
        this.name = name;
    }
    public String getName(){
        return name;
    }
}

class SecondChild extends ConstructorTest{
    private String name = null;
    public SecondChild(){
        this("super text 1", "Unknown");
    }
    public SecondChild(String name){
        this("super text 2", name);
    }
    private SecondChild(String superStr, String name)
    {
        super(superStr);
        this.name = name;
    }
    public String getName(){
        return name;
    }
}

public class ConstructorTest{
    public ConstructorTest(String str){
        System.out.println("ConstructorTest constructor called with parameter \"" + str + "\"");
    }
    public static void main(String... args)
    {
        System.out.println("Hello from main, FirstChild results:");
        FirstChild fc1 = new FirstChild();
        FirstChild fc2 = new FirstChild("John");
        System.out.println("           child fc1 name: " + fc1.getName());
        System.out.println("           child fc2 name: " + fc2.getName());
        System.out.println("Hello from main, SecondChild results:");
        SecondChild sc1 = new SecondChild();
        SecondChild sc2 = new SecondChild("John");
        System.out.println("           child sc1 name: " + sc1.getName());
        System.out.println("           child sc2 name: " + sc2.getName());
    }
}

0

super() - 指的是直接父类实例。 可用于调用直接父类方法。 this() - 指的是当前类实例。 可用于调用当前类方法。


0

由于构造函数调用必须是方法中的第一条语句,因此如果我们在一个方法中同时定义了this和super构造函数,那么就会发生冲突,如下所示。 假设首先调用此构造函数,则它将检查当前类构造函数,如果在当前类构造函数中有另一个方法调用或语句,则在此调用中,在调用超类构造函数之前将调用当前类构造函数内的所有方法和语句,然后将拒绝“构造函数调用必须是方法中的第一条语句”的语句。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接