构造函数的调用问题

aceor 2006-04-02 01:01:32
Abstract class A{
public A(){draw();}
abstract draw();
}
class B extends A{
public B(){}
void draw(){}
}
public class Test{
public static void main(String[] args){
B b=new B();
}
}
根据java里构造函数的递归调用过程,
1,B构造器构造对象的时候先调用A的构造器,
2,而A的构造器则会调用A的draw方法,
3,而B又是实现A的子类,则A的draw方法会调用B的draw方法,这时B又要调用A的构造器,
这样一来不是死循环了?不知道我这样理解对不对,
...全文
378 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
aceor 2006-04-03
  • 打赏
  • 举报
回复
UnAgain() 和bryantd(Delphi菜鸟)讲的大致意思是不是说:B中调用的就是自己的draw方法,这样B构造的时候只要调用到A的构造器就可以了,
class B extends A {
public B () {
System.out.println("A is constructing");
draw(); //这个就是自己的draw方法了?是吧?
System.out.println("B is constructing");
}

void draw(){
System.out.println("B.draw");
}
}
就像这样,恩,
hero222 2006-04-03
  • 打赏
  • 举报
回复
abstract class A{
public A(){
System.out.println("contruct A");
draw();
System.out.println("exit A");
}
abstract void draw();
}
class B extends A{
public B(){
System.out.println(" contructor b");
}
void draw(){
System.out.println("Class B");
}
}
public class Test{
public static void main(String[] args){
B b=new B();
}
}
结果是:
contruct A

Class B

exit A

contructor b

bryantd 2006-04-03
  • 打赏
  • 举报
回复
我给你一种我的理解,仍然用UnAgain()的例子,他的例子很好。
首先,所有基类的构造方法在子类的构造方法中都会第一个被调用(隐式或显式),如果基类是一个具体类,那么在调用子类实例化时也会实例化一个基类对象;如果基类是一个抽象类,因为抽象类不允许生成实例,所以就算执行了super(),也不会生成抽象基类的实例。所以对于抽象基类构造方法的作用,主要是对基类进行一些必要的初始化,这样就减轻了子类初始化的工作量(我自己是这么理解的,不知道对不对)
楼住的困惑应该是来自于抽象类中的那个抽象方法draw(),你的问题是为什么基类构造器好像“看到了”子类的具体draw()方法了,其实就像UnAgain()朋友说的,理解继承机制,记着把父类和子类扁平化。楼住不妨这样看待这个B类:
class B extends A {
public B () {
System.out.println("A is constructing");
draw();
System.out.println("B is constructing");
}

void draw(){
System.out.println("B.draw");
}
}
其实这样的模式就是对继承机制的一种应用,当然可能这种模式好像没什么实际意义。你在抽象基类构造器中调用这个具体方法真有什么具体应用价值?所以不建议。
还是应该在抽象基类中声明接口(抽象方法),在子类中根据子类的要实现的功能实现它,通过子类对象去调用,这是正常的模式。
qq14923349 2006-04-02
  • 打赏
  • 举报
回复
不明白
UnAgain 2006-04-02
  • 打赏
  • 举报
回复
B不是一个独立的类型,是基于A的扩展。构造B时,对A的构造是对B进行构造的必不可少的一部分。实际上,在构造B的时候,并没有类A的概念。在构造B时,其中对A的构造相当于是B在调用属于自身的一个方法,当然,这个方法比一般方法特殊一点。我把你的代码改变一下,我想你会明白。


public class TestConstructor {
public static void main(String[] args) {
B b = new B();
}
}

abstract class A {
public A () {
System.out.println("A is constructing");
draw();
}
abstract void draw();
}

class B extends A {
public B () {
// super(); // 构造子类时,这条语句总是默认执行。
System.out.println("B is constructing");
}

void draw(){
System.out.println("B.draw");
}
}

---------- 执行结果 ----------
// 首先默认执行super()
A is constructing
B.draw

// 执行自身语句
B is constructing
------------------------------

理解继承机制,记着把父类和子类扁平化。



挑大梁 2006-04-02
  • 打赏
  • 举报
回复
而B又是实现A的子类,则A的draw方法会调用B的draw方法,这时B又要调用A的构造器

是啊这句话有问题,函数写啊
lydvqq 2006-04-02
  • 打赏
  • 举报
回复
这里应是这样的.
1,B构造器构造对象的时候先调用A的构造器,
2,而A的构造器则会调用A的draw方法,
3,这里调用A的draw时,因为B实现A(我觉的也是一种覆盖方法.)的方法.那它就会去执行B的方法,不会再构造一个B,因此就不会再去调用A的构造方法了.
lydvqq 2006-04-02
  • 打赏
  • 举报
回复
则A的draw方法会调用B的draw方法,这时B又要调用A的构造器--A的方法并不是调用B的方法.而是一种override.
abstract class A{
public A(){
draw();
System.out.println("A");
}
abstract void draw();
}
class B extends A{
public B(){}
void draw(){
System.out.println("B");
}
}
public class test{
public static void main(String[] args){
B b=new B();
}
}
xsyl_1982 2006-04-02
  • 打赏
  • 举报
回复
楼上的说的有点道理,java中是不推荐构造器中调用其他函数的,不仅仅是抽象方法,因为这时类A还没初始化
eagle4510 2006-04-02
  • 打赏
  • 举报
回复
好像不能在构造器中调用抽像方法的,不推荐这么用。
widegoose_wy 2006-04-02
  • 打赏
  • 举报
回复
3,而B又是实现A的子类,则A的draw方法会调用B的draw方法,这时B又要调用A的构造器,

A的draw方法会调用B的draw方法后,A的构造过程就结束了啊。
然后B在开始完成剩下的构造过程就ok了。

yjws 2006-04-02
  • 打赏
  • 举报
回复
晕了...
B继承A(抽象类)
A里面出现的方法.B里都要继承下了.
aceor 2006-04-02
  • 打赏
  • 举报
回复
测试程序似乎没问题,谁能解释一下这里面的调用步骤呢?

62,626

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧