java学习笔记—初始化与清理
java初始化有两种,一种是在定义的时候就初始化,另外一种是在构造函数内初始化,这两种有什么区别呢?
public class Initial{ String s1="Initial at definition" String s2; public Initial(String s2) { this.s2=s2; } }
s1初始化是在进入到构造函数之前,所以当Initial对象创建的时候,s2是NUll。然而调用构造函数初始化s2,可以自由的让你选择初始化的值,而s1初始化的值是写死的!
在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,他们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
静态对象的初始化顺序先于“非静态对象”。
class Cup{ public Cup(int maker) { // TODO Auto-generated constructor stub System.out.println("Cup("+maker+")"); } void f(int maker){ System.out.println("f("+maker+")"); } } class Cups { static Cup cup1; static Cup cup2; static{ cup1 = new Cup(1); cup2 = new Cup(2); } public Cups() { // TODO Auto-generated constructor stub System.out.println("Cups()"); } } public class ExplicitStatic { public static void main(String[] args) { System.out.println("Inside main()"); Cups.cup1.f(99);//(1) } static Cups cups1 = new Cups();//(2) // static Cups cups2 = new Cups();//(2) }
无论通过标为(1)的那行代码访问静态的cup1对象,还是把标为(1)的行注释掉,让它去运行标为(2)的那行代码,Cups的静态初始化动作都会得到执行。如果把标为(1)和(2)的行同时注释掉,Cups的静态初始化动作就不会得到执行。此外激活一行还是两行(2)的代码都无关紧要,静态初始化动作只进行一次。
无论创建多少个对象,静态数据都只占用一份存储区域。static关键字不能应用于局部变量,因此它只能作用于域。如果一个域是静态的基本类型域,且没有对它进行初始化,那么它就会获得基本类型的标准初值;如果他是一个对象引用,那么它的默认初始化值就是null。
静态数据都只占用一份存储区域的意思是,只要在类中定义了静态变量。则该类创建的所有对象都共享该静态数据,改变该静态变量值,同时改变所有对象的该变量!如下代码所示,输出为
initClass2.snum=88
initClass1.snum=88
initClass2.inum=200
initClass1.inum=99
1 public class InitClass { 2 static int snum; 3 int inum=99; 4 public static void main(String[] args) { 5 InitClass initClass1 = new InitClass(); 6 InitClass initClass2 = new InitClass(); 7 snum = 88; 8 System.out.println("initClass2.snum="+initClass2.snum); 9 System.out.println("initClass1.snum="+initClass2.snum); 10 initClass1.inum = 200; 11 System.out.println("initClass2.inum="+initClass1.inum); 12 System.out.println("initClass1.inum="+initClass2.inum); 13 } 14 15 }
类中变量的初始化顺序如下图所示:
为了防止程序出现不可预料的错误,JAVA编程思想这本书建议在编写构造器时:用尽可能的简单的方法使对象进入到正常状态;如果可以的话,避免调用其他方法。在构造器内唯一能够安全调用的那些方法是基类中的final方法(也适用于private方法,private方法默认是funal方法),这些方法不能被覆盖。