Java中的默认构造函数和继承

时间:2009-02-08 11:10:36

标签: java inheritance initialization default-constructor

我对Java中的默认构造函数和继承有疑问。

通常,如果你编写一个类并且不包含任何构造函数,Java会自动为你提供一个默认构造函数(一个没有参数),它会初始化类的所有实例变量(如果有的话)并带有一些默认值( 0,null或false)。但是,如果使用某些参数编写构造函数,并且不编写任何默认构造函数,则Java不提供默认构造函数。 我的问题是:类是什么情况,它继承自其他类 - 如果我编写一个带有一些参数的构造函数,但是不包含默认构造函数,它们是否继承了超类的默认构造函数?

11 个答案:

答案 0 :(得分:61)

  1. 如果您不构建构造函数,the default empty constructor is automatically created

  2. 如果任何构造函数没有显式调用super或this构造函数作为其第一个语句a call to super() is automatically added

  3. 始终

答案 1 :(得分:52)

不继承构造函数。

此外,字段的初始化由虚拟机完成,而不是默认构造函数。默认构造函数只调用超类的默认构造函数,而Object的默认构造函数为空。这种设计的优点是无法访问未初始化的字段。

答案 2 :(得分:11)

除非你使用super(...),否则构造函数会调用其父级的空构造函数。 注意:它在所有类上执行此操作,甚至是扩展Object的类。

这不是继承,子类不会获得具有相同参数的相同构造函数。但是,您可以添加调用超类的构造函数之一的构造函数。

答案 3 :(得分:6)

基本规则是对构造函数的调用(或调用)应该是JVM需要执行的第一个语句,

因此,当你有一个只有参数化构造函数且没有默认构造函数的超类,并且基类没有对超类的参数化构造函数的显式调用时,JVM提供了super();由于没有超类的默认构造函数,因此抛出错误的调用,所以我们要么在超类中提供默认构造函数,要么在基类构造函数中显式调用超类的参数化构造函数。当我们给出显式调用时,那么JVM就懒得把行放到super();因为构造函数调用应该是方法的第一个语句,这是不可能发生的(因为我们的显式调用)。

答案 4 :(得分:5)

Java语言规范的第8.8.9节详细解释了发生了什么:

  

如果一个类不包含构造函数声明,那么默认构造函数是   隐含地宣布。顶级类的默认构造函数的形式,   成员类或本地类如下:

     
      
  • 默认构造函数与类具有相同的可访问性(第6.6节)。
  •   
  • 默认构造函数没有形式参数,非私有参数除外   内部成员类,默认构造函数隐式声明一个正式   表示类的直接封闭实例的参数(§8.8.1,   §15.9.2,§15.9.3)。
  •   
  • 默认构造函数没有throws子句。
  •   
  • 如果声明的类是原始类Object,那么是默认值   构造函数有一个空体。否则,简单的默认构造函数   调用没有参数的超类构造函数。
  •   

你可以看到这里没有继承:所有它都是带有隐式声明的默认构造函数的“编译魔术”。规范还明确指出,只有当类根本没有构造函数时才添加默认构造函数,这意味着你的问题的答案是“否”:一旦你给一个类一个构造函数,就可以访问它的默认构造函数超类失去了。

答案 5 :(得分:3)

如果您提供构造函数,那么Java将不会为您生成默认的空构造函数。所以你的派生类只能调用你的构造函数。

默认构造函数不会将您的私有变量初始化为默认值。证据是可以编写一个没有默认构造函数的类,并将其私有成员初始化为默认值。这是一个例子:

public class Test {

    public String s;
    public int i;

    public Test(String s, int i) {
        this.s = s;
        this.i = i;
    }

    public Test(boolean b) {
        // Empty on purpose!
    }

    public String toString() {
        return "Test (s = " + this.s + ", i = " +  this.i + ")";
    }

    public static void main (String [] args) {
        Test test_empty = new Test(true);
        Test test_full = new Test("string", 42);
        System.out.println("Test empty:" + test_empty);
        System.out.println("Test full:"  + test_full);
    }
}

答案 6 :(得分:2)

Thumb Rule是Sub Class应该从基类调用任何构造函数。因此,如果您没有默认的const,则从子类调用现有的const。另外明智地在基类中实现空const以避免编译问题

答案 7 :(得分:2)

你的问题的答案非常简单。隐式(不可见),任何构造函数中的第一个语句是' super();'即调用超类的无参数构造函数,直到你明确地将其更改为' this();',' this(int)',&# 39;该(字符串)','超级(INT)','超(字符串)'等等 '该();'是当前班级的构造函数。

答案 8 :(得分:1)

当我们不创建构造函数时,Java会自动创建默认构造函数。 但是当我们使用参数创建一个或多个自定义构造函数时,Java不会创建任何默认构造函数。 如果我们创建一个或多个构造函数并且我们想要创建一个没有任何构造函数参数的对象,我们必须声明一个空构造函数。

答案 9 :(得分:1)

编译时会出现错误...因为编译器会查找默认的Constructor他的超类,如果它不存在......那就是错误......并且程序不会编译......

答案 10 :(得分:0)

子类中的任何构造函数都将调用父类的no参数构造函数(或默认构造函数)。如果在父类中定义了参数化的构造函数,则必须使用super关键字显式调用父类的构造函数,否则会产生编译错误。

class Alpha 
{ 
    Alpha(int s, int p) 
    { 
        System.out.println("base");
    }

} 

public class SubAlpha extends Alpha 
{ 
    SubAlpha() 
    { 
        System.out.println("derived"); 
    } 
    public static void main(String[] args) 
    { 
        new SubAlpha(); 
    } 
}

上面的代码将给出编译错误:

prog.java:13: error: constructor Alpha in class Alpha cannot be applied to given types;
    { 
    ^
  required: int,int
  found: no arguments
  reason: actual and formal argument lists differ in length
1 error

发生上述错误是因为在父类中既没有参数构造函数/默认构造函数,也没有在子类中调用参数化构造函数。

现在要解决此问题,可以像这样调用参数化构造函数:

class Alpha 
{ 
    Alpha(int s, int p) 
    { 
        System.out.println("base");
    }

} 

public class SubAlpha extends Alpha 
{ 
    SubAlpha() 
    { 
        super(4, 5); // calling the parameterized constructor of parent class
        System.out.println("derived"); 
    } 
    public static void main(String[] args) 
    { 
        new SubAlpha(); 
    } 
}

输出

base
derived

在父类中定义一个无参数的构造函数,如下所示:

class Alpha 
{ 
    Alpha(){

    }
    Alpha(int s, int p) 
    { 
        System.out.println("base");
    }

} 

public class SubAlpha extends Alpha 
{ 
    SubAlpha() 
    { 
        System.out.println("derived"); 
    } 
    public static void main(String[] args) 
    { 
        new SubAlpha(); 
    } 
}

输出

derived