Java类如何没有no-arg构造函数?

时间:2011-03-12 23:36:26

标签: java constructor

Oracle Java教程网站的这一段令我感到困惑:

  

所有课程至少有一个   构造函数。如果一个课没有   显式声明任何,Java   编译器自动提供   无参数构造函数,称为   默认构造函数。这个默认值   构造函数调用类父类   无参数构造函数或Object   如果类没有其他的构造函数   家长。如果父母没有   构造函数(Object确实有一个),   编译器将拒绝该程序。

如果所有对象直接或间接地从Object继承,那么如何引出编译器拒绝?是否与私有的构造函数有关?

8 个答案:

答案 0 :(得分:31)

  

如果所有对象直接或间接地从Object继承,那么如何引出编译器拒绝?

我认为你误解的基础是你思考构造函数是继承的。实际上,构造函数不是用Java继承的。请考虑以下示例:

public class A {
    public A(int i) { super(); ... }
}

public class B extends A {
    public B() { super(); ... }
}

班级A

  • 不会继承Object
  • 中的任何构造函数
  • 未明确声明no-args构造函数(即public A() {...})和
  • 没有默认构造函数(因为它 声明了另一个构造函数)。

因此,它只有一个构造函数:public A(int)

super()类中对B的调用尝试在A中使用不存在的无参数构造函数,并给出编译错误。要解决此问题,您需要更改B构造函数以使用A(int)构造函数,或在A中声明显式的no-args构造函数。

(顺便说一句,构造函数没有必要显式地调用超类构造函数......就像我已经完成的那样。但是很多人认为包含显式调用是好的风格如果省略,Java编译器会对超类no-args构造函数插入一个隐式调用...如果no-args构造函数不存在或子类不可见,则会导致编译错误。)< / p>

  

是否与私有的构造函数有关?

不直接。但是,声明构造函数private将阻止从子类调用该构造函数。

答案 1 :(得分:15)

要理解的关键是,如果类还没有构造函数,那么no-arg构造函数将自动生成。

因此很容易创建一个没有no-arg构造函数的类。

答案 2 :(得分:9)

想到这个问题的最简单方法如下:

  1. 非args构造函数由Java为您创建的任何类提供为默认构造函数。

  2. 当您使用参数创建自定义构造函数时,Java会说“嘿,这个类有一个自定义构造函数,所以我不打算创建/提供默认的非args构造函数!” /强>”

  3. 结果现在你的类没有默认的非args构造函数。

  4. 这意味着当您根据类创建子类时,需要显式调用您创建的基于自定义构造函数的参数。

答案 3 :(得分:4)

如果你有一个子类的子类

class A 
{
    A(int i) {..}
}

class B extends A 
{
}

这里插入B的默认构造函数将尝试调用A的无参构造函数(它不存在),因为它只有一个构造函数接受一个参数

答案 4 :(得分:1)

对象的 immediate 超类必须具有受保护或公共构造函数(或者根本没有构造函数,在这种情况下将创建一个)。因此,如果我创建一个扩展Object的类,只使用私有构造函数,那么任何东西都无法扩展我的类。

答案 5 :(得分:1)

是。私有构造函数是一个特殊的实例构造函数。它通常用于仅包含静态成员的类中。如果一个类有一个或多个私有构造函数而没有公共构造函数,则不允许其他类(嵌套类除外)创建此类的实例。

私有构造函数的声明会阻止自动生成默认构造函数。

编辑:

  

在另一个类中定义的类   被称为嵌套类。像其他人一样   一个类的成员,一个嵌套类可以   被宣布为静态。一个   非静态嵌套类称为   内心阶级。 内心的一个例子   class只能存在于一个中   封闭类的实例和   可以访问其封闭类   成员,即使他们被宣布   私人

答案 6 :(得分:0)

这意味着如果你继承了一行使默认的no-arg构造函数为private(或者它不存在,例如)的类,你的子类必须声明一个符合的构造函数它的父母的替代构造函数。

例如,不允许使用以下Bar条声明:

public class Foo {
  private Foo() {  } // or this doesn't even exist
  public Foo(int i) {
  }
}
public class Bar extends Foo {
}

答案 7 :(得分:0)

让我附上所有上述一个有趣的案例,其中default / no-arg构造函数是不可行的,除非它是显式声明的,否则编译器不能假设它,但它与子类没有任何关系。这是一个具有final字段的类的情况,该字段需要构造函数初始化它。例如:

class Foo extends Object {
    private final Object o;

    public Foo(Object o){
       this.o = o;
    }
}

这里很容易看到Foo对象的实例化需要初始化最终字段o,因此任何Foo()的调用 - 无论是否直接 - 都注定要失败......我强调超类(Object)中的无参数构造函数存在且可公开访问,但最终字段(o)的存在会在Foo中停用它。