成员变量、方法执行顺序

——————————————————初始化案例1————————————————————

Tag

package initializationorder;

class Tag {
	Tag(int marker) {
		System.out.println("Tag(" + marker + ")");
	}
}

OrderOfInitialization

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 + ")");
	}
}

Mugs

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 + ")");
	}
}

情况1、

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);
}

Table

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);
}

StaticInitialization

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 章将要讲到的那样,这实际可能要求进行相当多的操作,特别是在涉及继承的时
候。


你可能感兴趣的:(成员变量、方法执行顺序)