package com.soft.init;
public class Meal
{
public Meal()
{
System.out.println("meal construct");
}
}
package com.soft.init;
public class Lunch extends Meal
{
static
{
System.out.println("lunch : static field");
}
{
System.out.println("lunch : not a static field");
}
public Lunch()
{
System.out.println("lunch construct");
}
}
package com.soft.init;
public class Bread
{
static
{
System.out.println("bread : static field");
}
{
System.out.println("bread : not a static field");
}
public Bread()
{
System.out.println("bread construct");
}
}
package com.soft.init;
public class PortableLunch extends Lunch
{
public static int FEE_OF_TEA = charge("tea");
static
{
System.out.println("PortableLunch : static field ");
}
private Bread bread = new Bread();
{
System.out.println("PortableLunch : not a static field");
}
public PortableLunch()
{
System.out.println("portableLunch construct");
}
public static int charge(String s)
{
System.out.println("you hava a cup of tea");
return s.length();
}
public static void main(String[] args)
{
new PortableLunch();
}
}
输出:
lunch : static field 父类静态成员
you hava a cup of tea 子类静态成员
PortableLunch : static field
meal construct 父类的父类构造方法(和父类对比下)
lunch : not a static field 父类非静态成员
lunch construct 父类构造方法
bread : static field 子类非静态成员
bread : not a static field
bread construct
PortableLunch : not a static field
portableLunch construct 子类构造方法
初始化顺序:父类静态成员 ----- 子类静态成员 ----- 父类非静态成员 ------- 父类构造方法 ----- 子类非静态成员 ----- 子类构造方法
子类非静态成员:若子类包含其他类(上例中的Bread类)作为自己的非静态成员变量,则在子类非静态成员的初始化过程中,也需要初始化Bread类。
单独类的初始化:静态成员 --- 非静态成员 ---- 构造方法
Thinking In Java page:199
这意味着对于一个复杂的对象,构建器的调用遵照下面的顺序:
(1) 调用基础类构建器。这个步骤会不断重复下去,首先得到构建的是分级结构的根部,然后是下一个衍生
类,等等。直到抵达最深一层的衍生类。
(2) 按声明顺序调用成员初始化模块。
(3) 调用衍生构建器的主体。
构建器调用的顺序是非常重要的。进行继承时,我们知道关于基础类的一切,并且能访问基础类的任何
public 和protected 成员。这意味着当我们在衍生类的时候,必须能假定基础类的所有成员都是有效的。采
用一种标准方法,构建行动已经进行,所以对象所有部分的成员均已得到构建。但在构建器内部,必须保证
使用的所有成员都已构建。为达到这个要求,唯一的办法就是首先调用基础类构建器。然后在进入衍生类构
建器以后,我们在基础类能够访问的所有成员都已得到初始化。此外,所有成员对象(亦即通过合成方法置
于类内的对象)在类内进行定义的时候(比如上例中的b,c 和l),由于我们应尽可能地对它们进行初始
化,所以也应保证构建器内部的所有成员均为有效。