日期:2014-05-20  浏览次数:20783 次

【一个关于类初始化顺序的问题】能帮我解释一下这段程序的运行结果吗?
Java code
class A {
  String name = isName();

  String isName() {
    System.out.println("222222222");
    return null;
  }

  A() {
    System.out.println("333333333");
  }
}

class B extends A {
  String name = isName();

  String isName() {
    super.isName();
    System.out.println("1111111111");
    return "aa";
  }
}

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


结果 

222222222
1111111111
333333333
222222222
1111111111

为什么初始化父类name的时候调用的是子类重写之后的方法?

------解决方案--------------------
探讨
因为A b=new B(); 的话,则在地址空间中开辟的是B的数据空间,
则B所有的方法,变量都是已经存储于内存空间中.
然后进行一个A b=new B();
就是当进行A对方法的调用,
因为A是父类,所有A有的方法B一定有,
因此A的所有方法都是可以调用得出来,
而如果在进行继承过程中,B重写了方法,
则调用的则是B重写的方法..这样就可以解释楼主的疑问了


------解决方案--------------------
答:很遗憾,13楼标示的次序并不正确。真正的第一步(不考虑父类Object的初始化)是父类A中的数据成员:
A类的name = isName(); <==这是第一步(不考虑父类[/color]Object的初始化时)
new B()时执行次序:(步骤如下:)
1:执行父类构造器A()=============》1.1执行父类Object的构造器
1.2执行A类的name = isName(); =>子类重写的isName()
1.2.1 执行:super.isName()
1.2.2执行:println("111111")
1.3执行A类构造器中:System.out.println("333333333"); 


2:执行B类中的:name = isName(); =>2.1 执行super.isName()
2.2 执行:System.out.println("111111")

3:执行B类构造器中的:System.out.println("/////////");

这样的运行结果是:
222222222
1111111111
333333333
222222222
1111111111
/////////

------解决方案--------------------
这里重要是要理解extends和A a=new B();
一。首先程序的入口main方法进入走到A a=new B(),如果对比A a=new B()和B a = new B();来看,其实他们起
到的作用是一样的,但从用法来说,A a=new B()是针对多态的向上转型,他的意义在于当A有子类的时候,
通过后期绑定能够准确的在A中调用到子类重写后的方法。而这种写法的意义在于只需要暴露父类的接口,
避免具体实现的代码泄露。所以,A a=new B()从代码的方面来说,他运行的过程和结果和B a = new B()
其实是一样的,之所以要写成这样,使为拉在后期开发中起到暴露父类接口,屏蔽子类代码的作用。
二。那么进入下一步,A a=new B(),可以确定的是,首先肯定是NEW拉一个B的实例出来,在这里,要知道的是
NEW的这个B的实例,他的具体内容是什么,要知道,B是extends A的,那么也就是说,伴随A的类方法是随
着extends被继承到拉B中,也就是说,用A的构造器构造拉B类,这里,子类B会自动调用父类A()的无参
构造方法来构造子类B,所以会出现
A() {
System.out.println("333333333");
}
那么他们的先后顺序又是怎么回事呢
class B extends A {
String name = isName(); //1

String isName() { //2
super.isName(); //3
System.out.println("1111111111");
return "aa";
}
}
如上,为运行1的时候调用道2,而2种的3又调用到父类中的isname方法,所以出现
222222222
1111111111
这并不奇怪
而当B中的1运行完,运行到2的时候,又重复拉一次,再次输出
222222222
1111111111
那么出现在中间的333333是不是告诉我们A的构造方法在在B类的
String name = isName();语句后被调用?这又是怎么一回事呢?难道说一个类的运行过程是
属性-〉构造方法-〉普通方法?但既然是=isName(),那就必然isName()方法先于String name出现,
不然不可能得到调用。 
那么我自己觉得比较好的解释就是B继承A的时候,把A中的属性方法的顺序也继承拉的,呵呵,想不通啦
哪位兄弟来帮我解惑


 
------解决方案--------------------
反问楼主一个问题啊,先看代码

class A {
String name = isName();

private String isName() {
System.out.println("222222222");
return null;
}

A() {
System.out.println("333333333");
System.out.println("this是"+this.getClass()+"类型的对象");