Java:抽象类构造函数和 this()
有人可以指出我的误解吗?
我有两个类,一个抽象类和一个具体类,如下所示:
public abstract class Abstract
{
protected static int ORDER = 1;
public static void main (String[] args)
{
Concrete c = new Concrete("Hello");
}
public Abstract()
{
Class c = this.getClass();
System.out.println(ORDER++ + ": Class = "
+ c.getSimpleName()
+ "; Abstract's no-arg constructor called.");
}
public Abstract(String arg)
{
this();
Class c = this.getClass();
System.out.println(ORDER++ + ": Class = "
+ c.getSimpleName()
+ "; Abstract's 1-arg constructor called.");
}
}
当
public class Concrete extends Abstract
{
public Concrete()
{
super();
Class c = this.getClass();
System.out.println(ORDER++ + ": Class = "
+ c.getSimpleName()
+ "; Concrete's no-arg constructor called.");
}
public Concrete(String arg)
{
super(arg);
Class c = this.getClass();
System.out.println(ORDER++ + ": Class = "
+ c.getSimpleName()
+ "; Concrete's 1-arg constructor called.");
}
}
我运行它时,我得到以下输出:
1) 类 = 混凝土;摘要的无参数 调用构造函数。
2) 类别 = 具体的; Abstract 的 1-arg 构造函数 打电话。
3)类别=混凝土; 调用 Concrete 的 1-arg 构造函数。
我的问题是:为什么 Abstract 的 String arg 构造函数对 this() 的调用不调用 Concrete 上的无参数构造函数?或者,也许更相关的是,有没有办法让 Abstract 的 String arg 构造函数调用 Concrete 上的无参数构造函数,从而允许构造函数的“正确”链接?
Can someone point out what I'm misunderstanding?
I've got two classes, an Abstract and a Concrete, as follows:
public abstract class Abstract
{
protected static int ORDER = 1;
public static void main (String[] args)
{
Concrete c = new Concrete("Hello");
}
public Abstract()
{
Class c = this.getClass();
System.out.println(ORDER++ + ": Class = "
+ c.getSimpleName()
+ "; Abstract's no-arg constructor called.");
}
public Abstract(String arg)
{
this();
Class c = this.getClass();
System.out.println(ORDER++ + ": Class = "
+ c.getSimpleName()
+ "; Abstract's 1-arg constructor called.");
}
}
and
public class Concrete extends Abstract
{
public Concrete()
{
super();
Class c = this.getClass();
System.out.println(ORDER++ + ": Class = "
+ c.getSimpleName()
+ "; Concrete's no-arg constructor called.");
}
public Concrete(String arg)
{
super(arg);
Class c = this.getClass();
System.out.println(ORDER++ + ": Class = "
+ c.getSimpleName()
+ "; Concrete's 1-arg constructor called.");
}
}
When I run this I get the following output:
1) Class = Concrete; Abstract's no-arg
constructor called.
2) Class =
Concrete; Abstract's 1-arg constructor
called.
3) Class = Concrete;
Concrete's 1-arg constructor called.
My question is this: why doesn't the call to this() from Abstract's String arg constructor call this no-arg constructor on Concrete? Or, perhaps more pertinently, is there any way to get Abstract's String arg constructor to call the no-arg constructor on Concrete, allowing a "proper" chaining of Constructors?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
否 - 构造函数链接总是要么横向(在同一类型中)要么向上(到父类型)。
不要忘记调用必须在编译时解析 - 并且 Abstract 不知道其他类将从它派生什么,或者它们的构造函数是什么会有的。
您可以在
Abstract
构造函数中调用虚拟方法,并在Concrete
中重写该方法...但我强烈建议您不要 来做到这一点。特别是,Concrete
的构造函数主体尚未执行,变量初始值设定项也不会执行 - 因此它无法对Concrete
执行任何操作 -具体状态。在某些非常的特定情况下,这样做是正确的,但这种情况很少见,应谨慎处理。你到底想做什么?通常我发现最好有许多“横向”链通向具有“向上”链的单个构造函数。
No - constructor chaining always goes either sideways (in the same type) or upwards (to the parent type).
Don't forget that the call has to be resolved at compile-time - and
Abstract
doesn't know what other classes are going to derive from it, or what constructors they'll have.You could call a virtual method within the
Abstract
constructor, and override that method withinConcrete
... but I would urge you not to do that. In particular, the constructor body forConcrete
won't have been executed yet, and neither will the variable initializers - so it wouldn't be able to do anything withConcrete
-specific state. There are some very specific situations where that's the correct thing to do, but they're rare and should be handled with caution.What are you actually trying to do? Usually I find it's better to have many "sideways" chains leading to a single constructor which has the "upward" chain.
事情就是这样(Jon Skeet 详细介绍)。
不过,您可以向 Concrete 添加一个 init 块:
与默认构造函数相反,初始化器块始终被调用:
That's simply the way it is (as detailed by Jon Skeet).
You could add an init block to Concrete though:
In contrast to the default constructor, the inizializer block is always called:
这是帖子重点关注抽象类的需求及其工作原理。希望这会对您有所帮助。
Here is the post which focus on what the need of abstract class and how it works.May this will help you.
您应该知道子类始终对父类隐藏。您不能像在子类中那样直接调用子类的方法或构造函数。
You should have to know that a child class is always hidden from the parent class. You can't call the method or constructor of child class directly like you did in child class.
处理这个问题的最佳方法通常是让一个类的所有构造函数最终使用一个公共构造函数,即:
the best way to handle this is generally to have all constructors for a class end up using one common constructor, i.e.: