Java编程思想学习笔记(十)
5.6成员初始化
Java尽力保证所有变量在使用之前都被初始化,当然,编译器也可能帮你赋一个初值,但是这样反而会掩盖程序里的疏忽,所以还是尽量由程序员提供这个初值。
若数据成员为基本类型,那么编译器会在程序员没有给予初始值的情况下给他们一个约定好的默认值。定义对象引用时,若不将其初始化,那么其默认值为null。
5.6.1指定初始化:
也就是在定义变量的时候就为他赋初值,这种方法相当灵活,甚至可以调用某种方法,使用其返回值来作为初值(这个方法可以带有参数,但是这个参数必须是初始化完成的)。
5.7构造器初始化
可以使用构造器来进行初始化工作,但是无论如何,这无法阻止自动初始化的发生,它将在构造器被调用之前发生。
5.7.1初始化顺序:
在类的内部,变量定义的先后顺序决定了初始化的顺序,即时变量定义散布在方法定义之间,在任何一个方法被调用前,变量会全部得到初始化。
5.7.2静态数据的初始化:
无论创建多少个对象,静态数据都只占用一份存储区域,下面的例子体现了静态变量的初始化的时机和顺序:
1 import com.sun.tracing.dtrace.StabilityLevel;//这个没用() 2 3 class Bowl{ 4 Bowl(int marker){ 5 System.out.println("Bowl(" + marker + ")"); 6 } 7 void f1(int marker){ 8 System.out.println("f1(" + marker + ")"); 9 } 10 } 11 class Table{ 12 static Bowl bowl1 = new Bowl(1); 13 Table(){ 14 System.out.println("Table()"); 15 bowl2.f1(1); 16 } 17 void f2(int marker){ 18 System.out.println("f2(" + marker + ")"); 19 } 20 Bowl bowl2 = new Bowl(2); 21 } 22 class Cupboard{ 23 Bowl bowl3 = new Bowl(3); 24 static Bowl bowl4 = new Bowl(4); 25 Cupboard(){ 26 System.out.println("Cupboard()"); 27 bowl4.f1(2); 28 } 29 void f3(int marker){ 30 System.out.println("f3(" + marker + ")"); 31 } 32 static Bowl bowl5 = new Bowl(5); 33 } 34 public class StaticCreateOrder { 35 public static void main(String[] args){ 36 System.out.println("Creating new Cupboard() in main1"); 37 new Cupboard(); 38 System.out.println("Creating new Cupboard() in main2"); 39 new Cupboard(); 40 table.f2(1); 41 cupboard.f3(1); 42 } 43 static Table table = new Table(); 44 static Cupboard cupboard = new Cupboard(); 45 }
// Bowl(1) // Bowl(2) // Table() // f1(1) // Bowl(4) // Bowl(5) // Bowl(3) // Cupboard() // f1(2) // Creating new Cupboard() in main1 // Bowl(3) // Cupboard() // f1(2) // Creating new Cupboard() in main2 // Bowl(3) // Cupboard() // f1(2) // f2(1) // f3(1)
输出结果
从上面的例子可以看出,无论是在哪个类中,都会先对static类型的成员进行初始化。完成调用栈(类似栈的结构)所有静态变量的初始化之后才会开始进行方法调用。
5.7.3显式的静态初始化:
Java允许将多个静态初始化动作组织成一个特殊的“静态子句”(静态块)
也就是初始化静态变量的另一种写法()。
class StaticGroup{ static int i; static { i = 47; } }
和其他初始化动作一样,这段代码仅在第一次生成这个类的对象(或首次访问这个类的静态数据成员)时执行一次。
5.7.4非静态实例初始化:
和上面的静态实例初始化类似,只不过这次只是大括号括起来(没static)。这种方法对于支持匿名内部类的初始化是必须的,但是他也使得你可以保证无论调用了哪个显式构造器,某些操作都会发生,实例初始化子句也是在构造器调用前执行的。
2.16上传 P132