简体   繁体   English

如果父类具有带参数的构造函数,为什么需要在父类中使用默认构造函数?

[英]Why default constructor is required in a parent class if it has an argument-ed constructor?

Why default constructor is required(explicitly) in a parent class if it has an argumented constructor如果父类具有带参数的构造函数,为什么在父类中需要(显式)默认构造函数

class A {    
  A(int i){    
  }
}

class B extends A {
}

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

This will be an error.这将是一个错误。

There are two aspects at work here:这里有两个方面在起作用:

  • If you do specify a constructor explicitly (as in A ) the Java compiler will not create a parameterless constructor for you.如果您确实明确指定了构造函数(如在A ),则 Java 编译器不会为您创建无参数构造函数。

  • If you don't specify a constructor explicitly (as in B ) the Java compiler will create a parameterless constructor for you like this:如果您没有显式指定构造函数(如在B ),Java 编译器将为您创建一个无参数构造函数,如下所示:

     B() { super(); }

(The accessibility depends on the accessibility of the class itself.) (可访问性取决于类本身的可访问性。)

That's trying to call the superclass parameterless constructor - so it has to exist.那是试图调用超类无参数构造函数 - 所以它必须存在。 You have three options:您有三个选择:

  • Provide a parameterless constructor explicitly in AA显式提供无参数构造函数
  • Provide a parameterless constructor explicitly in B which explicitly calls the base class constructor with an appropriate int argument.B中显式提供无参数构造函数,该构造函数使用适当的int参数显式调用基类构造函数。
  • Provide a parameterized constructor in B which calls the base class constructorB提供一个参数化构造函数,它调用基类构造函数

Why default constructor is required(explicitly) in a parent class if it has an argumented constructor如果父类具有带参数的构造函数,为什么在父类中需要(显式)默认构造函数

I would say this statement is not always correct.我会说这种说法并不总是正确的。 As ideally its not required .理想情况下它不是必需的

The Rule is : If you are explicitly providing an argument-ed constructer, then the default constructor (non-argumented) is not available to the class.规则是:如果您显式提供了带参数的构造函数,则该类无法使用默认构造函数(无参数)。

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

class B extends A {
}

So when you write所以当你写

B obj_b = new B();

It actually calls the implicit constructor provided by java to B, which again calls the super(), which should be ideally A().它实际上调用了java提供的隐式构造函数给B,B又调用了super(),理想情况下应该是A()。 But since you have provided argument-ed constructor to A, the default constructor i:e A() is not available to B().但是由于您为 A 提供了带参数的构造函数,因此默认构造函数 i:e A() 对 B() 不可用。

That's the reason you need A() to be specifically declared for B() to call super().这就是您需要为 B() 专门声明 A() 以调用 super() 的原因。

Every subclass constructor calls the default constructor of the super class, if the subclass constructor does not explicitly call some other constructor of the super class.如果子类构造函数没有显式调用超类的其他构造函数,则每个子类构造函数都会调用超类的默认构造函数。 So, if your subclass constructor explicitly calls a super class constructor that you provided (with arguments), then there is no need of no arguments constructor in the super class.因此,如果您的子类构造函数显式调用您提供的超类构造函数(带参数),则超类中不需要无参数构造函数。 So, the following will compile:因此,将编译以下内容:

class B extends A{
     B(int m){
        super(m);
     }
}

But the following will not compile, unless you explicitly provide no args constructor in the super class:但是以下不会编译,除非您在超类中明确提供没有 args 构造函数:

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

Assuming that you meant to write class B extends A :假设您打算编写class B extends A

Every constructor has to call a superclass constructor;每个构造函数都必须调用超类构造函数; if it does not the parameterless superclass constructor is called implicitly.如果不是,则隐式调用无参数超类构造函数。

If (and only if) a class declares no constructor, the Java compiler gives it a default constructor which takes no parameters and calls the parameterless constructor of the superclass.如果(且仅当)一个类没有声明构造函数,Java 编译器会给它一个默认构造函数,它不带参数并调用超类的无参数构造函数。 In your example, A declares a constructor and therefor does not have such a default constructor.在您的示例中, A声明了一个构造函数,因此没有这样的默认构造函数。 Class B does not declare a constructor, but cannot get a default constructor because its superclass does not have a parameterless constructor to call.B没有声明构造函数,但无法获得默认构造函数,因为它的超类没有可调用的无参数构造函数。 Since a class must always have a constructor, this is a compiler error.由于类必须始终具有构造函数,因此这是编译器错误。

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

Not necessarily!不必要!

Now in your class B现在在你的 B 班

class B extends A {
}

you have not provided any constructor in Class B so a default constructor will be placed.您尚未在 B 类中提供任何构造函数,因此将放置默认构造函数。 Now it is a rule that each constructor must call one of it's super class constructor.现在的规则是每个构造函数都必须调用它的超类构造函数之一。 In your case the default constructor in Class B will try to call default constructor in class A(it's parent) but as you don't have a default constructor in Class A(as you have explicitly provided a constructor with arguments in class A you will not have a default constructor in Class A ) you will get an error.在您的情况下,B 类中的默认构造函数将尝试调用 A 类(它的父类)中的默认构造函数,但由于您在 A 类中没有默认构造函数(因为您在 A 类中明确提供了一个带参数的构造函数,因此您将在 A 类中没有默认构造函数)你会得到一个错误。

What you could possibly do is你可能会做的是

Either provide no args constructor in Class A.在 A 类中不提供 args 构造函数。

A()
{
  //no arg default constructor in Class A
}

OR要么

Explicitly write no args constructor in B and call your super with some default int argument.明确地在 B 中写入 no args 构造函数,并使用一些默认的 int 参数调用您的 super。

B()
{
    super(defaultIntValue);
}

Bottom line is that for an object to be created completely constructors of each parent in the inheritance hierarchy must be called.底线是,要创建一个对象,必须调用继承层次结构中每个父级的完全构造函数。 Which ones to call is really your design choice.调用哪个实际上是您的设计选择。 But in case you don't explicitly provide any java will put default constructor super() call as 1st line of each of your sub class constructors and now if you don't have that in superclass then you will get an error.但是,如果您没有明确提供任何 java 会将默认构造函数 super() 调用作为每个子类构造函数的第一行,现在如果您在超类中没有它,那么您将收到错误。

There are a few things to be noted when using constructors and how you should declare them in your base class and super class.使用构造函数时需要注意一些事项,以及如何在基类和超类中声明它们。 This can get somewhat confusing solely because there can be many possibilities of the availability or existence of constructors in the super class or base class.这可能会变得有些混乱,因为超类或基类中构造函数的可用性或存在性可能有很多。 I will try to delve into all the possibilities:我将尝试深入研究所有可能性:

  • If you explicitly define constructors in any class(base class/super class), the Java compiler will not create any other constructor for you in that respective class.如果您在任何类(基类/超类)中显式定义构造函数,Java 编译器将不会在相应的类中为您创建任何其他构造函数。

  • If you don't explicitly define constructors in any class(base class/super class), the Java compiler will create a no-argument constructor for you in that respective class.如果您没有在任何类(基类/超类)中显式定义构造函数,Java 编译器将在相应的类中为您创建一个无参数的构造函数。

  • If your class is a base class inheriting from a super class and you do not explicitly define constructors in that base class, not only will a no-argument constructor be created for you (like the above point) by the compiler, but it will also implicitly call the no-argument constructor from the super class.如果您的类是从超类继承的基类,并且您没有在该基类中显式定义构造函数,则编译器不仅会为您创建无参数构造函数(如上点),而且还会从超类隐式调用无参数构造函数。

     class A { A() { super(); } }
  • Now if you do not explicity type super(), (or super(parameters)), the compiler will put in the super() for you in your code.现在,如果您没有明确键入 super()、(或 super(parameters)),编译器会在您的代码中为您放入 super()。
  • If super() is being called (explicitly or implicitly by the compiler) , the compiler will expect your superclass to have a constructor without parameters.如果 super() 被调用(由编译器显式或隐式调用),编译器将期望您的超类具有不带参数的构造函数。 If it does not find any constructor in your superclass without parameters, it will give you a compiler error.如果它在你的超类中没有找到任何没有参数的构造函数,它会给你一个编译器错误。

  • Similary if super(parameters) is called, the compiler will expect your superclass to have a constructor with parameters(number and type of parameters should match).类似地,如果调用 super(parameters) ,编译器将期望您的超类具有带参数的构造函数(参数的数量和类型应匹配)。 If it does not find such a constructor in your superclass, it will give you a compiler error.如果它在你的超类中找不到这样的构造函数,它会给你一个编译器错误。 ( Super(parameters) can never be called implicitly by the compiler. It has to be explicitly put in your code if one is required.) ( Super(parameters) 永远不能被编译器隐式调用。如果需要,它必须显式地放入你的代码中。)

We can summarize a few things from the above rules我们可以从上面的规则中总结出一些东西

  • If your superclass only has a constructor with parameters and has no no-argument constructor, you must have an explicit super(parameters) statement in your constructor.如果您的超类只有一个带参数的构造函数而没有无参数的构造函数,则您的构造函数中必须有一个显式的 super(parameters) 语句。 This is because if you do not do that a super() statement will be implicitly put in your code and since your superclass does not have a no-argument constructor, it will show a compiler error.这是因为如果您不这样做, super() 语句将隐式放入您的代码中,并且由于您的超类没有无参数构造函数,它将显示编译器错误。
  • If your superclass has a constructor with parameters and another no-argument constructor, it is not necessary to have an explicit super(parameters) statement in your constructor.如果你的超类有一个带参数的构造函数和另一个无参数的构造函数,那么你的构造函数中就没有必要有一个显式的 super(parameters) 语句。 This is because a super() statement will be implicitly put in your code by the compiler and since your superclass has a no-argument constructor, it will work fine.这是因为编译器会隐式地将 super() 语句放入您的代码中,并且由于您的超类具有无参数构造函数,因此它可以正常工作。
  • If your superclass only has a no-argument constructor you can refer to the point above as it is the same thing.如果你的超类只有一个无参数的构造函数,你可以参考上面的观点,因为它是一样的。

Another thing to be noted is if your superclass has a private constructor, that will create an error when you compile your subclass.另一件要注意的事情是,如果您的超类有一个私有构造函数,那么在您编译子类时会产生错误。 That is because if you don't write a constructor in your subclass it will call the superclass constructor and the implicit super() will try to look for a no-argument constructor in the superclass but will not find one.这是因为如果您不在子类中编写构造函数,它将调用超类构造函数,而隐式 super() 将尝试在超类中查找无参数构造函数但找不到。

Say this compiled, what would you expect it to print?说这个编译,你希望它打印什么?

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

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

When A is constructed a value for i has to be passed, however the compiler doesn't know what it should be so you have specify it explicitly in a constructor (any constructor, it doesn't have to be a default one)当 A 被构造为i ,必须传递一个值,但是编译器不知道它应该是什么,因此您必须在构造函数中明确指定它(任何构造函数,它都不必是默认的)

When we have parameter constructor.当我们有参数构造函数时。 we explicit bound to consumer by design.我们通过设计明确绑定到消费者。 he can not create object of that class without parameter.他不能在没有参数的情况下创建该类的对象。 some time we need to force user to provide value.有时我们需要强制用户提供价值。 object should be created only by providing parameter(default value).对象只能通过提供参数(默认值)来创建。

class Asset
{
    private int id;
    public Asset(int id)
    {
        this.id = id;
    }
}

class Program
{
    static void Main(string[] args)
    {
        /* Gives Error - User can not create object. 
         * Design bound
         */
        Asset asset1 = new Asset();/* Error */
    }
}

Even child class can not create.连子类都不能创建。 hence it is behavior of good design.因此,这是良好设计的行为。

When extending a class, the default superclass constructor is automatically added.扩展类时,会自动添加默认的超类构造函数。

public class SuperClass {
}

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

If you've overloaded your super class constructor, however, this takes the place of the default and invoking super() will thus cause a compile error as it is no longer available.但是,如果您重载了超类构造函数,这将取代默认值,因此调用super()将导致编译错误,因为它不再可用。 You must then explicitly add in the overloaded constructor or create a no-parameter constructor.然后,您必须显式添加重载的构造函数或创建一个无参数的构造函数。 See below for examples:请参阅以下示例:

public class SuperClass {
   public SuperClass(String s, int x) {
     // some code
   }
}

public class SubClass extends SuperClass {
   public SubClass(String s, Product... someProducts) {
      super("some string", 1);
   }
}

OR...要么...

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
   }
}

因为如果您想阻止创建没有任何数据的对象,这是一种好方法。

Of course its an error if written like this it's not JAVA.当然,如果这样写它是一个错误,它不是JAVA。

If you would have use JAVA syntax it wouldn't be an error.如果您将使用 JAVA 语法,则不会出错。

Class A and B knows nothing about each other if in separate files/packages.如果在单独的文件/包中,A 类和 B 类对彼此一无所知。

Class A doesn't need a default constructor at all it works fine with only a parameter constructor. A 类根本不需要默认构造函数,它只使用参数构造函数就可以正常工作。

If B extends A you simple use a call to super(int a) in B's constructor and everything is fine.如果 B 扩展了 A,您只需在 B 的构造函数中调用 super(int a) ,一切都很好。 for constructors not calling a super(empty/or not) extending a super class the compiler will add a call to super().对于不调用扩展超类的 super(空/或不)的构造函数,编译器将添加对 super() 的调用。

For further reading look at Using the Keyword super如需进一步阅读,请参阅使用关键字超级

I would guess that its because when you have an empty parameter list the super variable can't be instantiated.我猜这是因为当您有一个空参数列表时,无法实例化超级变量。 With empty parameter list I mean the implicit super() the compiler could add if the super class had a nonparametric constructor.对于空参数列表,我的意思是如果超类具有非参数构造函数,编译器可以添加隐式 super() 。

For example if you type:例如,如果您键入:

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

You will get an error with what I think is the same logic error.你会得到一个错误,我认为是相同的逻辑错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么在Java中键入自变量构造函数时未提供默认构造函数? - Why the default constructor is not provided when typing an argument-ed constructor in java? 即使子类已经有一个已定义的构造函数,父类是否总是需要一个默认或无参数的构造函数? - Does a parent class always need a default or no-argument constructor even if the child class already has a defined constructor? 如果对象是超类且无参数构造函数具有空体,那么默认构造函数如何用于实例化对象? - How does default constructor used to instantiate object if it's super class no argument constructor has empty body? 不建议使用默认构造函数时如何调用父类的构造函数 - How to call constructor of parent class when the default constructor is deprecated 错误:-服务类没有零参数构造函数 - error:- service class has no zero argument constructor Java:子类的构造函数具有父类的Object - Java: Constructor of a subclass has an Object of parent class Java:没有默认构造函数的类的newInstance - Java: newInstance of class that has no default constructor 为什么EnumMap构造函数需要类参数? - Why EnumMap constructor needs class argument? 没有默认的构造函数 - has no default constructor 为什么反序列化时不为父类调用构造函数? - Why constructor is not called for the parent class while deserialization?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM