Thinking In Java笔记(第五章 初始化与清理(三))

第五章 初始化与清理5.6 成员初始化

Java尽力保证:所有变量在使用前都能得到恰当的初始化。对于方法的局部变量,Java以编译错误的形式来保证。如下:

void f() {int i;i++; //Error:i not initialized}

会得到一条错误的消息,提示i可能没有初始化。编译器可以给i赋初值,但是并没有这么做,因为没有初始化是程序员的疏忽,为了保证程序的稳定性,能帮助程序员找出程序的缺陷所在。

但如果是类的数据成员是基本类型,类的每个基本类型成员变量都会保证有一个初值。如下:

public class Test {boolean t;char c;byte b;short s;int i;long l;float f;double d;InitialValues reference;}

上面的一系列数值分别为:false, (空白), 0, 0, 0, 0, 0.0, 0.0, null。char值为0,所以显示为空白。

5.6.1 指定初始化

有一种很直接的方法给某个变量赋初值,就是在定义类成员变量的地方直接为其赋值,C++中不允许。对初始化非基本类型的对象也可以,例如下面的A类的对象,这样类Test的每个对象都会具有相同的初始值。如下:

class A{}public class Test {boolean bool = true;char ch = ‘x’;int i = 99;A a = new A();}5.7 构造器初始化

还可以用构造器来进行初始化。在运行时刻,可以调用方法或执行某些动作来确定初值,这给编程带来了更大的灵活性。但是要记住,无法组织自动初始化的进行,也就是前面提到的编译器自动赋值,这个工作在构造器被调用之前就发生。例如:

public class Test {int i;Test() {i = 7;} }

i的值首先被置为0,再被赋值为7。

5.7.1 初始化顺序

在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布与方法定义之间,它们人就会在任何方法(包括构造器)被调用之前得到初始化。例如:

class Window {Window(int maker) {System.out.println(“Window(” + maker + “)”);}}class House {Window w1 = new Window(1);House() {System.out.println(“House”);w3 = new Window(33);}Window w2 = new WIndow(2);void f() {System.out.println(“f()”);Window w3 = new Window(3);}}public class Test {public static void main(String[] args) {House h = new House();h.f();} }

结果为Window(1) Window(2) Window(3) House() Window(33) f()。

5.7.2 静态数据的初始化

无论创建多少个对象,静态数据都至占用一份存储区域。static关键字不能应用于局部变量。看下面的例子:

class Bowl {Bowl(int marker) {System.out.println(“Bowl(” + marker + “)”);}void f1(int marker) {System.out.println(“f1(” + marker + “)”);}}class Table {static Bowl bowl1 = new Bowl(1);Table() {System.out.println(“Table()”);bowl2.f1(1);void f2(int marker) {System.out.println(“f2(” + marker + “)”);}static Bowl bowl2 = new Bowl(2);}class Cupboard {Bowl bowl3 = new Bowl(3);static Bowl bowl4 = new Bowl(4);Cupboard() {System.out.println(“Cupboard()”);bowl4.f1(2);}void f3(int marker) {System.out.println(“f3(” + marker + “)”);}static Bowl bowl5 = new Bowl(5);}}public class Test {public static void main(String[] args){System.out.println(“Creating new Cupboard() in main”);new Cupboard();Syste.out.println(“Creating new Cupboard() in main”);new Cupboard();table.f2(1);cupboard.f3(1);}static Table table = new Table();static Cupboard cupboard = new Cupbpard();}

输出的结果依次为:

Bowl(1) Bowl(2) Table() f1(1) Bowl(4)Bowl(5)Bowl(3) Cupboard()f1(2) Creating new Cupboard() in main Bowl(3)Cupboard() f1(2) Creating new Cupboard() in main Bowl(3)Cupboard()f1(2)f2(1)f3(1)

静态初始化只有在必要的时候才会进行,只有在第一个类对象被创建(或第一次访问静态数据)的时候,静态数据才会被初始化。之后,无论怎么创建对象,都不会再次被初始化。

初始化的顺序是先静态对象(如果它们尚未被初始化),而后是”非静态对象”。

总结一下对象的创建过程,假设有个名为Dog的类:

5.7.3 显示的静态初始化

Java允许多个静态初始化动作组织成一个特殊的”静态子句”(有时也叫做”静态块”)。就像下面这样:

public class Spoon {static int i;static {i = 47;}}

和其他静态初始化动作一样,这段代码只执行一次:当首次生成这个类的对象时,或首次访问属于这个类的静态成员数据的时候执行。例如:

class Cup {Cup(int marker) {System.out.println(“Cup(” + marker + “)”);}void f(int marker) {System.out.println(“f(” + marker + “)”);}}class Cups {static Cup cup1;static Cup cup2;static {cup1 = new Cup(1);cup2 = new Cup(2);}Cups() {System.out.println(“Cups()”);}}public class Test {public static void main(String[] args) {System.out.println(“Inside main()”);Cups.cup1.f(99); // (1)}//static Cups cups1 = new Cups(); // (2)//static Cups cup2 = new Cups(); // (2)}

上面的结果为:Inside main() Cup(1) Cup(2) f(99)

5.7.4 非静态实例初始化

Java中也有被成为实例初始化的类似语法,用来初始化每一个对象的非静态变量。和静态语句块一样的,只不过少了static。如果不创建类的实例,非静态语句块是不会被执行,只会触碰static变量和语句块。

下面用一个例子来总结下上述的顺序:

class Cup {{System.out.println(“Block – Cup”);}static int c;static {c = 1;System.out.println(“Static Bolck – Cup”);}Cup(int marker) {System.out.println(“Construct – Cup(” + marker + “)”);}void f(int marker) {System.out.println(“Function – f(” + marker + “)”);}}class Cups {static {cup1 = new Cup(1);cup2 = new Cup(2);}static Cup cup1;static Cup cup2;{System.out.println(“Block – Cups”);}Cups() {System.out.println(“Construct – Cups()”);}}public class JavaTest {public static void main(String[] args) {System.out.println(“Inside main()”);Cups.cup1.f(99); // (1)}}

输出的结果为:

Inside main()Static Bolck – CupBlock – CupConstruct – Cup(1)Block – CupConstruct – Cup(2)Function – f(99)做对的事情比把事情做对重要。

Thinking In Java笔记(第五章 初始化与清理(三))

相关文章:

你感兴趣的文章:

标签云: