相信好多人对Java初始化问题一直存有疑惑,下面是我看到的比较详细的java初始化问题讲解

一  java初始化基础知识
1、 一个类的所有基本类型数据成员都会保证获得一个初始值。 
非基本类型,会初始化为null 


package cn.edu.xidian.w3ang.javabasic;
public class JavaInitialization
{
	int a;
	char b;
	short s;
	float f;
	long lo;
	double dou;
	byte e;
	boolean flag;
	Object obj;

	public static void main(String[] args)
	{
		JavaInitialization init = new JavaInitialization();
		init.print();
	}
    //int a=0, char b=口,  short s=0, float f=0.0, long lo=0, 
	//double dou=0.0, byte e=0, boolean flag=false, Object obj=null
	public void print()
	{
		System.out.println("int a=" + a + ", char b=" + b + ", " + " short s=" + s + 
				", float f=" + f + ", long lo="+ lo + ", double dou=" + dou + ", byte e=" 
				+ e + ", boolean flag=" + flag + "," + " Object obj=" + obj);
	}
}

出来结果为 

int a=0, char b=口, short s=0, float f=0.0, long lo=0, double dou=0.0, byte e=0, boolean flag=false, Object obj=null

可见,java会为类的基本类型的变量提供一个初始值,各类型初始值不同,非基本类型初始为null。注意,这里的变量必须是类变量,注意,只会为类变量提供初始化,而局部变量不会。如果局部变量没有初始化,会收到一个出错信息 

 

2、可以通过构造方法或其他方法进行初始化,但是不会妨碍java默认的初始化

  看下面的例子 


package cn.edu.xidian.w3ang.javabasic;
public class JavaInitialization2
{
	int i;
	Object obj;
	public JavaInitialization2()
	{
		System.out.println("before i=" + i + "  obj=" + obj);
		i = 1;
		obj = new Object();
		System.out.println("after i=" + i + " obj=" + obj);
	}
	/* OutPut:
	before i=0  obj=null
	after i=1 obj=java.lang.Object@2a139a55
	*/
	public static void main(String[] args)
	{
		JavaInitialization2 init = new JavaInitialization2();
	}
}

由此可见,不论是基本类型,还是其他的类。java默认的初始化是最先发生的,位于一切方法之前。 

3、static 数据的初始化 
  static 数据会发生上述同样的事情(基本类型,获得对应基本类型的初始化值;非基本类型,初始化为null) 
  但是,由于static值只有一个存储区域,所以static值只会被初始化一次,看下面的例子 



package cn.edu.xidian.w3ang.javabasic;

public class JavaInitialization3
{
	public static void main(String[] args)
	{
		Cupboard cup = new Cupboard();
		cup = new Cupboard();
	}
}
/*
	init ing Bowl~
	initialization Cupboard
	initialization Cupboard
 */
class Cupboard
{
	static Bowl bowl = new Bowl();
	public Cupboard()
	{
		System.out.println("initialization Cupboard");
	}
}

class Bowl
{
	public Bowl()
	{
		System.out.println("init ing Bowl~");
	}
}

所以说,static数据只会在第一次进行初始化,之后就不会了。 

4、初始化顺序 
  在一个类中,无论变量的定义是在方法之前还是方法之后,都会在方法之前进行初始化的; 
  另外,static数据初始化位于非static数据初始化之前 
来看下边的例子 



package cn.edu.xidian.w3ang.javabasic;

public class JavaInitialization4
{
	public static void main(String[] args)
	{
		Cupboard2 cupboard2 = new Cupboard2();
	}
}
/*
 init ing Bowl2~
 initialization Pan
 initialization Cupboard2
 */

class Cupboard2
{
	Pan pan = new Pan();
	public Cupboard2()
	{
		System.out.println("initialization Cupboard2");
	}
	static Bowl2 bowl = new Bowl2();
}

class Bowl2
{
	public Bowl2()
	{
		System.out.println("init ing Bowl2~");
	}
}

class Pan
{
	public Pan()
	{
		System.out.println("initialization Pan");
	}
}

5、静态块 
  静态块里的变量初始化顺序位于普通变量之前,和static变量相比,则是完全由定义的顺序来决定了。另外,静态块里的变量也是只初始化一次,这点和static变量一致。示例如下 


package cn.edu.xidian.w3ang.javabasic;

public class JavaInitialization5
{
	static
	{
		Bowl3 bowl3 = new Bowl3(2);
	}

	private Bowl3 bowl3 = new Bowl3(3);
	static Bowl3 bowl = new Bowl3(1);
	/*
	init ing Bowl3: 2
	init ing Bowl3: 1
	init ing Bowl3: 3

	init ing Bowl3: 3
	*/
	public static void main(String[] args)
	{
		JavaInitialization5 other = new JavaInitialization5();
		System.out.println();
		other = new JavaInitialization5();
	}
}

class Bowl3
{
	public Bowl3()
	{
		System.out.println("init ing Bowl3~: ");
	}

	public Bowl3(int i)
	{
		System.out.println("init ing Bowl3: " + i);
	}
}

如果调换static变量和静态块的位置,输出结果如下 



static Bowl3 bowl = new Bowl3(1);
	private Bowl3 bowl3 = new Bowl3(3);
	static
	{
		Bowl3 bowl3 = new Bowl3(2);
	}
	/*
	init ing Bowl3: 1
	init ing Bowl3: 2
	init ing Bowl3: 3

	init ing Bowl3: 3
	*/



6、涉及到继承时 初始化顺序 
  初始化时,如果有static变量或静态块,其初始化顺序是位于最前面的,无论变量位于子类还是父类中,它们二者之间的顺序,可参见第5点; 
static变量初始完了后,先初始化父类,然后是子类。
 
  示例如下 


package cn.edu.xidian.w3ang.javabasic;

class Bowls
{
	public Bowls(int i)
	{
		System.out.println("initing Bowls: " + i);
	}
}

class Base
{
	Bowls bowl = new Bowls(1);
	public Base()
	{
		System.out.println("initialization Class Base");
	}
	static Bowls bowl5 = new Bowls(5);
	static
	{
		Bowls bowl6 = new Bowls(6);
	}
}

class Sub extends Base
{
	Bowls bowl2 = new Bowls(2);
	public Sub()
	{
		System.out.println("initialize Sub");
	}
	static Bowls bowl3 = new Bowls(3);
	static
	{
		Bowls bowl4 = new Bowls(4);
	}
}
/*
	initing Bowls: 5//有static变量或静态块,其初始化顺序是位于最前面的,无论变量位于子类还是父类中
	initing Bowls: 6//有static变量或静态块,其初始化顺序是位于最前面的,无论变量位于子类还是父类中
	initing Bowls: 3//有static变量或静态块,其初始化顺序是位于最前面的,无论变量位于子类还是父类中
	initing Bowls: 4//有static变量或静态块,其初始化顺序是位于最前面的,无论变量位于子类还是父类中
	initing Bowls: 1//然后是:父类的非static成员变量
	initialization Class Base//然后是:父类的非static构造方法
	initing Bowls: 2//然后是:子类的非static成员变量
	initialize Sub//然后是:子类的非static构造方法
*/
public class JavaInitialization6
{
	public static void main(String[] args)
	{
		new Sub();
	}
}



二 问题举例

package cn.edu.xidian.w3ang.javabasic;

class Singleton
{
	private static Singleton obj = new Singleton();//执行后,counter1、counter2均为1
	public static int counter1;
	public static int counter2 = 0;//counter2:由1改为0

	private Singleton()
	{
		counter1++;
		counter2++;
	}

	public static Singleton getInstance()
	{
		return obj;
	}
}

public class SingletonTest
{
	//obj.counter1==1
	//obj.counter2==0
	public static void main(String[] args)
	{
		Singleton obj = Singleton.getInstance();
		System.out.println("obj.counter1==" + obj.counter1);
		System.out.println("obj.counter2==" + obj.counter2);
	}
}

相信大家跟我一样会对这个结果存有疑问,这段代码中尤其注意:private static Singleton obj = new Singleton();   在类Singleton中的位置,改变位置会有不同结果。关于这段代码运行结果的解释:

当程序执行private static Singleton obj = new Singleton(); 句的时候就去调用了Singleton构造器,此时counter1、counter2都是1,但是接着执行向下执行:public static int counter1;时将1赋给counter1,执行public static int counter2 = 0;时重新给counter2赋值为0

 

三  典型初始化例子

Java初始话很好的一个例子, 摘自Think in Java


package cn.edu.xidian.w3ang.javabasic;

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

	static Bowl_ bowl5 = new Bowl_(5);
}

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_();
		table.f2(1);
		cupboard.f3(1);
	}

	static Table table = new Table();
	static Cupboard_ cupboard = new Cupboard_();
}/*
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)
*/
//无论创建多少对象, 静态数据都只占用一份存储区域  
//初始化的顺序是先静态对象(如果它们尚未因前面的对象创建过程而被初始化), 而后是"非静态"对象  
//载入.class文件(这将创建Class对象),有关静态初始化的所有动作执行.  
//静态初始化只在Class对象首次加载的时候进行一次