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

时间:2011-08-25 09:12:06

标签: java

如果父类具有参数化构造函数

,为什么需要(显式)默认构造函数
class A {    
  A(int i){    
  }
}

class B extends A {
}

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

这将是一个错误。

12 个答案:

答案 0 :(得分:67)

这里有两个方面:

  • 如果您执行明确指定构造函数(如A中所述),Java编译器将为您创建无参数构造函数。

  • 如果没有显式指定构造函数(如在B中),Java编译器将为您创建一个无参数构造函数:

    B()
    {
        super();
    }
    

(可访问性取决于类本身的可访问性。)

那是试图调用超类无参数构造函数 - 所以它必须存在。您有两种选择:

  • A
  • 中明确提供无参数构造函数
  • B中显式提供无参数构造函数,该构造函数使用适当的int参数显式调用基类构造函数。

答案 1 :(得分:11)

为什么在父类中需要(显式)默认构造函数,如果它有一个有争议的构造函数

我想说这句话并不总是正确的。理想情况下不需要

规则是:如果您明确提供参数化的构造函数,则该类无法使用默认构造函数(非参数化)。

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

class B extends A {
}

所以当你写

B obj_b = new B();

它实际上调用java提供的隐式构造函数给B,它再次调用super(),理想情况下应该是A()。但是既然你已经为A提供了参数化的构造函数,那么默认构造函数i:e A()不可用于B()。

这就是你需要为B()专门声明A()来调用super()的原因。

答案 2 :(得分:8)

如果子类构造函数没有显式调用超类的其他构造函数,则每个子类构造函数都会调用超类的默认构造函数。因此,如果您的子类构造函数显式调用您提供的超类构造函数(带参数),那么超类中不需要任何参数构造函数。 所以,以下将编译:

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

但是除非你在超类中明确地没有提供args构造函数,否则以下内容将无法编译:

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

答案 3 :(得分:7)

假设您打算写class B extends A

每个构造函数都必须调用超类构造函数;如果不是,则隐式调用无参数超类构造函数。

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

答案 4 :(得分:4)

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类中不提供args构造函数。

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

OR

在B中明确写出没有args构造函数,并使用一些默认的int参数调用你的super。

B()
{
    super(defaultIntValue);
}

底线是,对于要创建的对象,必须完全调用继承层次结构中每个父项的构造函数。要调用的是您的设计选择。但是如果你没有明确地提供任何java会将默认构造函数super()调用作为每个子类构造函数的第一行,现在如果你没有在超类中那么,那么你将得到一个错误。

答案 5 :(得分:2)

使用构造函数时需要注意几点,以及如何在基类和超类中声明它们。这可能有点令人困惑,因为在超类或基类中可能存在构造函数的可用性或存在的许多可能性。我将尝试深入研究所有可能性:

  • 如果在任何类(基类/超类)中显式定义构造函数,Java编译器将不会在相应的类中为您创建任何构造函数。

  • 如果没有在任何类(基类/超类)中显式定义构造函数,Java编译器将在相应的类中为您创建一个无参构造函数。

  • 如果你的类是继承自超类的基类而你没有在那个基类中显式定义构造函数,那么不仅会为你创建一个无参构造函数(如上所述)由编译器,但它也将从超类中隐式调用无参数构造函数。

    class A 
    {
       A() 
     {
      super();
     }
    }
    
  • 现在如果你没有表达类型super(),(或super(参数)),编译器会在你的代码中为你输入super()。
  • 如果正在调用super()(编译器显式或隐式),编译器将期望您的超类具有不带参数的构造函数。如果它没有在没有参数的超类中找到任何构造函数,它将给你一个编译器错误。

  • 类似如果调用super(参数),编译器会希望你的超类有一个带参数的构造函数(参数的数量和类型应匹配)。如果它在您的超类中找不到这样的构造函数,它将给您一个编译器错误。 (编译器永远不能隐式调用超级(参数)。如果需要,必须将其显式放入代码中。)

我们可以从上述规则中总结一些内容

  • 如果您的超类只有一个带参数的构造函数且没有无参构造函数,那么您的构造函数中必须有一个显式的super(parameters)语句。这是因为如果不这样做,super()语句将隐式放入您的代码中,并且由于您的超类没有无参数构造函数,它将显示编译器错误。
  • 如果您的超类具有带参数的构造函数和另一个无参构造函数,则不必在构造函数中使用显式的super(参数)语句。这是因为编译器会在你的代码中隐式地放入一个super()语句,因为你的超类有一个无参构造函数,它会正常工作。
  • 如果你的超类只有一个无参数的构造函数,你可以参考上面的观点,因为它是一样的。

另外需要注意的是,如果您的超类具有私有构造函数,那么在编译子类时会产生错误。那是因为如果不在子类中编写构造函数,它将调用超类构造函数,而隐式的super()将尝试在超类中查找无参数构造函数,但不会找到它。

答案 6 :(得分:1)

说这个编译好了,你期望它打印什么?

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

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

当构造A时,必须传递i的值,但编译器不知道它应该是什么,所以你在构造函数中明确指定它(任何构造函数,它不必是一个默认的)

答案 7 :(得分:0)

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

如果您使用JAVA语法,则不会出错。

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

A类根本不需要默认的构造函数,只有参数构造函数才能正常工作。

如果B扩展A,你可以在B的构造函数中使用对super(int a)的调用,一切都很好。 对于不调用super(空/或不)扩展超类的构造函数,编译器将添加对super()的调用。

如需进一步阅读,请查看Using the Keyword super

答案 8 :(得分:0)

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

例如,如果您输入:

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

我认为同样的逻辑错误会出错。

答案 9 :(得分:0)

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

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

即使是儿童班也无法创造。因此它是良好设计的行为。

答案 10 :(得分:0)

扩展类时,会自动添加默认的超类构造函数。

# Import twitter related packages
import json
import tweepy

from tweepy.streaming import StreamListener
from tweepy import OAuthHandler
from tweepy import Stream

#import request style packages

import requests
from urllib.request import urlopen, Request

# Import visualisation packages

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

# Store OAuth authentication credentials in relevant variables
access_token = "priv"
access_token_secret = "priv"

consumer_key = "priv"
consumer_secret = "priv"

# Pass OAuth details to tweepy's OAuth handler

auth = tweepy.OAuthHandler("priv", "priv")
auth.set_access_token("priv", "priv")

api = tweepy.API(auth)

import xlrd
import openpyxl

#Read and write to excel
dataFileUrl = R"C:/Users/cbaba/Desktop/algeria1.xlsx"


data = pd.read_excel(dataFileUrl, usecols = ['Tweet'])
datalist = data.values.tolist()

tweetref = []

for t in range (0,1):
    tweetref.extend(datalist[40:50])


for x in range(len(tweetref)):
    try:
        alpha = tweetref[x]
        tweet = api.statuses_lookup(tweetref)
        print(tweet.text)

    except:
       pass

但是,如果您已重载了超类构造函数,则它将代替默认构造函数,并且调用public class SuperClass { } public class SubClass extends SuperClass { public SubClass(String s, Product... someProducts) { //super(); <-- Java automatically adds the default super constructor } } 将导致编译错误,因为它不再可用。然后,您必须显式添加重载的构造函数或创建无参数的构造函数。参见以下示例:

super()

或...

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

答案 11 :(得分:0)

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