Java 如果父类有一个带参数的构造函数,为什么它需要默认构造函数?

Java 如果父类有一个带参数的构造函数,为什么它需要默认构造函数?,java,Java,如果父类有一个经过论证的构造函数,为什么它(显式地)需要默认构造函数 class A { A(int i){ } } class B extends A { } class Main { public static void main(String a[]){ B b_obj = new B(); } } 这将是一个错误。这里有两个方面在起作用: 如果确实显式指定构造函数(如a),Java编译器将不会为您创建无参数构造函数 如果没有明确指定

如果父类有一个经过论证的构造函数,为什么它(显式地)需要默认构造函数

class A {    
  A(int i){    
  }
}

class B extends A {
}

class Main {    
  public static void main(String a[]){
    B b_obj = new B();
  }
}

这将是一个错误。

这里有两个方面在起作用:

  • 如果确实显式指定构造函数(如
    a
    ),Java编译器将不会为您创建无参数构造函数

  • 如果没有明确指定构造函数(如
    B
    ),Java编译器将为您创建一个无参数构造函数,如下所示:

    B()
    {
        super();
    }
    
(可访问性取决于类本身的可访问性。)

这是试图调用超类无参数构造函数——因此它必须存在。您有三种选择:

  • a
  • B
    中显式提供无参数构造函数,该构造函数使用适当的
    int
    参数显式调用基类构造函数
  • B
    中提供一个参数化构造函数,它调用基类构造函数

当然,如果这样写的话这是一个错误,它不是JAVA

如果您使用JAVA语法,那么这不会是一个错误

如果在单独的文件/包中,A类和B类彼此一无所知

类根本不需要默认构造函数,它只需要一个参数构造函数就可以正常工作

如果B扩展了A,您只需在B的构造函数中调用super(intA),一切都正常。 对于未调用扩展超类的super(空/或非)的构造函数,编译器将添加对super()的调用


要进一步阅读,请查看假设您打算编写
类B扩展A

每个构造函数都必须调用一个超类构造函数;如果没有,则隐式调用无参数超类构造函数


如果(且仅当)一个类声明没有构造函数,Java编译器会给它一个默认构造函数,它不接受任何参数,并调用超类的无参数构造函数。在您的示例中,
A
声明了一个构造函数,因此没有这样的默认构造函数。类
B
未声明构造函数,但无法获取默认构造函数,因为其超类没有可调用的无参数构造函数。由于类必须始终具有构造函数,这是一个编译器错误。

如果是已编译的,您希望它打印什么

class A{
  A(int i){
    System.out.println("A.i= "+i);
  }
}

class B extends A {
  public static void main(String... args) {
    new B();
  }
}

当一个构造函数被构造时,必须为
i
传递一个值,但是编译器不知道它应该是什么,所以您必须在构造函数中显式指定它(任何构造函数,都不必是默认构造函数)

为什么需要默认构造函数(显式)在父类中,如果它具有经过论证的构造函数

我想说,这种说法并不总是正确的。理想情况下,不需要它

规则是:如果显式提供参数化构造函数,则默认构造函数(非参数化)对类不可用

For Example :   
class A {    
  A(int i){    
  }
}

class B extends A {
}
所以当你写作的时候

B obj_b = new B();
它实际上将java提供的隐式构造函数调用到B,B再次调用super(),理想情况下super()应该是A()。但是,由于您为A提供了参数化构造函数,默认构造函数i:ea()对B()不可用


这就是为什么需要特别声明A(),以便B()调用super()。

我猜这是因为当参数列表为空时,无法实例化super变量。对于空参数列表,我指的是如果超类具有非参数构造函数,编译器可以添加的隐式super()

例如,如果键入:

int a;
System.out.print(a);

您将得到一个错误,我认为是相同的逻辑错误。

当我们有参数构造函数时。我们通过设计明确地约束消费者。如果没有参数,他无法创建该类的对象。有时我们需要强迫用户提供价值。对象只能通过提供参数(默认值)来创建

即使是子类也不能创建。因此,这是良好设计的行为

Why default constructor is required(explicitly) in a parent class if it 
has an argumented constructor
不一定

现在在你的B班

class B extends A {
}
您尚未在类B中提供任何构造函数,因此将放置默认构造函数。现在有一条规则,每个构造函数必须调用它的一个超类构造函数。在您的情况下,类B中的默认构造函数将尝试调用类A中的默认构造函数(它的父类),但由于类A中没有默认构造函数(因为您在类A中显式提供了带参数的构造函数,所以在类A中不会有默认构造函数),您将得到一个错误

你能做的就是

在类A中不提供参数构造函数。

A()
{
  //no arg default constructor in Class A
}
B()
{
    super(defaultIntValue);
}

在B中显式地不写args构造函数,并使用一些默认的int参数调用super。

A()
{
  //no arg default constructor in Class A
}
B()
{
    super(defaultIntValue);
}

底线是,要完全创建对象,必须调用继承层次结构中每个父级的构造函数。哪一个是你真正的设计选择。但是,如果您没有显式提供任何java,则会将默认构造函数super()调用作为每个子类构造函数的第一行,现在如果在超类中没有,则会出现错误。

每个子类构造函数都会调用超类的默认构造函数,如果子类构造函数没有显式调用超类的其他构造函数。因此,如果您的子类构造函数显式调用您提供的超类构造函数(带有参数),那么在超类中就不需要无参数构造函数。
A()
{
  //no arg default constructor in Class A
}
B()
{
    super(defaultIntValue);
}
因此,将编译以下内容:

class B extends A{
     B(int m){
        super(m);
     }
}
但是,除非在超类中显式地不提供args构造函数,否则不会编译以下内容:

class B extends A{
     int i; 
     B(int m){
        i=m;
     }
}

在使用构造函数时,有几点需要注意
public class SuperClass {
   public SuperClass() {
     // can be left empty.
   }
}

public class SubClass extends SuperClass {
   public SubClass(String s, Product... someProducts) {
      //super(); <-- Java automatically adds the no-parameter super constructor
   }
}