Java 类怎么可能没有无参构造函数呢?
Oracle Java 教程网站有这样一段让我困惑的内容:
所有类都至少有一个 构造函数。如果一个类没有 显式声明任何,Java 编译器自动提供一个 无参构造函数,称为 默认构造函数。这个默认的 构造函数调用父类的 无参构造函数,或对象 如果类没有其他构造函数 父母。如果家长没有 构造函数(对象确实有一个), 编译器将拒绝该程序。
如果所有对象都直接或间接继承自 Object,如何可能引发所说的编译器拒绝?这与构造函数是私有的有关系吗?
The Oracle Java tutorial site has this paragraph that is confusing me:
All classes have at least one
constructor. If a class does not
explicitly declare any, the Java
compiler automatically provides a
no-argument constructor, called the
default constructor. This default
constructor calls the class parent's
no-argument constructor, or the Object
constructor if the class has no other
parent. If the parent has no
constructor (Object does have one),
the compiler will reject the program.
If all objects directly or indirectly inherit from Object how is it possible to elicit the compiler rejection spoken of? Does it have to do with the constructor being private?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我认为您误解的基础是您认为构造函数是继承的。事实上,Java 中的构造函数不是继承的。因此,请考虑以下示例:
类
A
:Object
继承任何构造函数,public A() {...}
),并且因此,它有且仅有一个构造函数:
public A(int)
。对
B
类中的super()
的调用尝试在A
中使用不存在的无参数构造函数,并给出编译错误。要解决此问题,您需要更改B
构造函数以使用A(int)
构造函数,或者在A
中声明显式无参数构造函数代码>.(顺便说一句,构造函数没有必要显式调用超类构造函数......就像我所做的那样。但是很多人认为包含显式调用是一种很好的风格。如果您忽略它,Java 编译器会插入对超类无参数构造函数的隐式调用……如果无参数构造函数不存在或对子类不可见,则会导致编译错误。)
不直接。但是,将构造函数声明为私有将阻止从子类调用该构造函数。
I think the basis is of your misunderstanding is that you are thinking that constructors are inherited. In fact, constructors are NOT inherited in Java. So consider the following example:
The class
A
:Object
,public A() {...}
), andHence, it has one and only one constructor:
public A(int)
.The call to
super()
in theB
class tries to use a non-existent no-args constructor inA
and gives a compilation error. To fix this, you either need to change theB
constructor to use theA(int)
constructor, or declare an explicit no-args constructor inA
.(Incidentally, it is not necessary for a constructor to explicitly call a superclass constructor ... as I've done. But a lot of people think it is good style to include an explicit call. If you leave it out, the Java compiler inserts an implicit call to the superclasses no-args constructor ... and that results in a compilation error if the no-args constructor does not exist or is not visible to the subclass.)
Not directly. However, declaring a constructor private will prevent that constructor being called from a child class.
要理解的关键是,如果类还没有构造函数,则仅会自动生成无参数构造函数。
因此,创建一个没有无参数构造函数的类很容易。
The key thing to understand is that the no-arg constructor will only be automatically generated if the class doesn't already have a constructor.
It's thus easy to create a class that doesn't have a no-arg constructor.
思考这个问题的最简单方法如下:
Java 为您创建的任何类提供非参数构造函数作为默认构造函数。
当你创建一个带有参数的自定义构造函数时,Java 会说“嘿,这个类有一个自定义构造函数,所以我不会费心创建/提供默认的非参数构造函数! ”
因此,现在您的类没有默认的非参数构造函数。
这意味着当您根据您的类创建子类时,您需要显式调用您创建的基于参数的自定义构造函数。
The simplest way to think of this problem is as follows:
The non-args constructor is provided as the default constructor by Java for any class you create.
The moment you create a custom constructor with arguments, Java says “hey, this class has got a custom constructor, so I am not going to bother creating/supplying the default non-args constructor!”
As a result now your class does NOT has the default non-args constructor.
This means when you create a subclass, based on your class, you need explicitly call the arguments based custom constructor that you created.
如果您有子类的子类
这里插入到 B 中的默认构造函数将尝试调用 A 的无参数构造函数(该构造函数不存在),因为它只有一个构造函数接受一个争论
If you have a sub-class of a sub-class
Here the default constructor inserted into
B
will try to invoke A's no-argument constructor (which doesn't exist) as it only has a constructor taking one argument对象的直接超类必须具有受保护或公共构造函数(或者根本没有构造函数,在这种情况下将创建一个构造函数)。因此,如果我创建一个扩展 Object 的类,仅使用私有构造函数,那么没有任何东西能够扩展我的类。
The immediate superclass of the object must have a protected or public constructor (or no constructor at all, in which case one will be created). So, if I create a class that extends Object, with a private constructor only, then nothing will be able to extend my class.
是的。私有构造函数是特殊的实例构造函数。它通常用于仅包含静态成员的类。如果一个类有一个或多个私有构造函数并且没有公共构造函数,则不允许其他类(嵌套类除外)创建该类的实例。
私有构造函数的声明可以防止自动生成默认构造函数。
编辑:
Yes. A private contructor is a special instance constructor. It is commonly used in classes that contain static members only. If a class has one or more private constructors and no public constructors, then other classes (except nested classes) are not allowed to create instances of this class.
The declaration of a private constructor prevents the automatic generation of a default constructor.
EDIT:
这意味着,如果您从一行类继承,该类将默认的无参数构造函数设为私有(或者例如它不存在),则您的子类必须声明一个与其父类的替代构造函数一致的构造函数构造函数。
例如,不允许使用以下 Bar 声明:
What this means is that if you inherit from a line of class(es) that make the default no-arg constructor private (or it does not exist, for example), your sub-classes must declare a constructor in line with its parent's alternative constructor.
For example, the following declaration of Bar is not allowed:
让我在上述所有内容中附加一个更有趣的情况,其中默认/无参数构造函数是不可行的,从某种意义上说,除非显式声明它,否则编译器无法假设它,但它与子类化无关。这是一个带有
final
字段的类的情况,该字段需要构造函数来初始化它。例如:在这里很容易看出 Foo 对象的实例化需要最终字段
o
的初始化,因此任何Foo()
的调用 - 直接或不 -注定要失败...让我强调一下,超类 (Object
) 中的无参数构造函数存在并且可以公开访问,但它是最终字段 (o< /code>),在
Foo
中停用它。Let me append to all aforementioned one more interesting case where the default/no-arg constructor is infeasible, in the sense that unless it is explicitly declared, the compiler cannot assume it and yet it has nothing to do with subclassing. This is the case of having a class with a
final
field which expects a constructor to initialize it. For example:Here it's easy to see that an instantiation of a Foo-object requires the initialization of the final field
o
so any invocation ofFoo()
- directly or not - is doomed to failure... Let me underline that the no-arg constructor in the super class (Object
) exists and is publicly accessible but it is the presence of the final field (o
) that deactivates it inFoo
.