——————————————————初始化案例1————————————————————
Tag
package initializationorder; class Tag { Tag(int marker) { System.out.println("Tag(" + marker + ")"); } }
package initializationorder; class Card { Tag t1 = new Tag(1); Card() { System.out.println("Card()"); t3 = new Tag(33); } Tag t2 = new Tag(2); void f() { System.out.println("f()"); } Tag t3 = new Tag(3); } public class OrderOfInitialization { public static void main(String[] args) { Card t = new Card(); t.f(); } }
Tag(1) Tag(2) Tag(3) Card() Tag(33) f()
在一个类里,初始化的顺序是由变量在类内的定义顺序决定的。即使变量定义大量遍布于方法定义的中间,
那些变量仍会在调用任何方法之前得到初始化—— 甚至在构建器调用之前
——————————————————案例2——————————
Mug
package InstanceInitialization; class Mug { Mug(int marker) { System.out.println("Mug(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } }
package InstanceInitialization; public class Mugs { Mug c1; Mug c2; { c1 = new Mug(1); c2 = new Mug(2); System.out.println("c1 & c2 initialized"); } Mugs() { System.out.println("Mugs()"); } public static void main(String[] args) { System.out.println("Inside main()"); Mugs x = new Mugs(); } }
Inside main() Mug(1) Mug(2) c1 & c2 initialized Mugs()非静态代码块变量仍会在调用任何方法之前得到初始化—— 甚至在构建器调用之前
——————————————————案例3————————————————
Cup
package staticinitialization; class Cup { Cup(int marker) { System.out.println("Cup(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } }
package staticinitialization; class Cups { static Cup c1; static Cup c2; static { c1 = new Cup(1); c2 = new Cup(2); } Cups() { System.out.println("Cups()"); } } public class ExplicitStatic { public static void main(String[] args) { System.out.println("Inside main()"); } static Cups x = new Cups(); // (2) }
Cup(1) Cup(2) Cups() Inside main()一旦 static Cups x = new Cups(); 就会去先加载static静态代码块,在去执行构造方法
情况2、
package staticinitialization; class Cups { static Cup c1; static Cup c2; static { c1 = new Cup(1); c2 = new Cup(2); } Cups() { System.out.println("Cups()"); } } public class ExplicitStatic { public static void main(String[] args) { System.out.println("Inside main()"); } static Cups x = new Cups(); // (2) static Cups y = new Cups(); // (2) }
Cup(1) Cup(2) Cups() Cups() Inside main()因为静态区域只加载一次
——————————————————案例4——————————————————
Bowl
package StaticDataInitialization; class Bowl { Bowl(int marker) { System.out.println("Bowl(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } }Cupboard
package StaticDataInitialization; class Cupboard { Bowl b3 = new Bowl(3); static Bowl b4 = new Bowl(4); Cupboard() { System.out.println("Cupboard()"); b4.f(2); } void f3(int marker) { System.out.println("f3(" + marker + ")"); } static Bowl b5 = new Bowl(5); }
package StaticDataInitialization; class Table { static Bowl b1 = new Bowl(1); Table() { System.out.println("Table()"); b2.f(1); } void f2(int marker) { System.out.println("f2(" + marker + ")"); } static Bowl b2 = new Bowl(2); }
package StaticDataInitialization; public class StaticInitialization { public static void main(String[] args) { System.out.println("Creating new Cupboard() in main"); new Cupboard(); System.out.println("Creating new Cupboard() in main"); new Cupboard(); t2.f2(1); t3.f3(1); } static Table t2 = new Table(); static Cupboard t3 = new Cupboard(); }
Bowl(1) Bowl(2) Table() f(1) Bowl(4) Bowl(5) Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) f2(1) f3(1)
在这里有必要总结一下对象的创建过程。请考虑一个名为 Dog 的类:
(1) 类型为 Dog 的一个对象首次创建时,或者 Dog 类的 static 方法/ static 字段首次访问时, Java 解释器
必须找到 Dog.class(在事先设好的类路径里搜索)。
(2) 找到 Dog.class 后(它会创建一个 Class 对象,这将在后面学到),它的所有 static 初始化模块都会运
行。因此, static 初始化仅发生一次—— 在 Class 对象首次载入的时候。
(3) 创建一个 new Dog()时, Dog 对象的构建进程首先会在内存堆( Heap)里为一个 Dog 对象分配足够多的存
储空间。
(4) 这种存储空间会清为零,将 Dog 中的所有基本类型设为它们的默认值(零用于数字,以及 boolean 和
char 的等价设定)。
(5) 进行字段定义时发生的所有初始化都会执行。
(6) 执行构建器。正如第 6 章将要讲到的那样,这实际可能要求进行相当多的操作,特别是在涉及继承的时
候。