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();
}
}
这将是一个错误。这里有两个方面在起作用:
- 如果确实显式指定构造函数(如
),Java编译器将不会为您创建无参数构造函数a
- 如果没有明确指定构造函数(如
),Java编译器将为您创建一个无参数构造函数,如下所示:B
B() { super(); }
- 在
a
- 在
中显式提供无参数构造函数,该构造函数使用适当的B
参数显式调用基类构造函数int
- 在
中提供一个参数化构造函数,它调用基类构造函数B
要进一步阅读,请查看假设您打算编写
类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
}
}