一个Java类中会定义各种变量、方法和代码块。其中方法和代码块从存在的意义上来讲,都是为了操作这些变量的。所以就笔者个人理解,类的主体该是变量,方法和代码块是为变量而存在的。

变量值的改变有两种情形,一是在进行初始化的时候,而是在方法中对其进行操作的时候。变量值改变的先后顺序将直接影响到程序运行的正确与否,所以理正确理解变量值在Java中如何改变对于一个优秀码农来说,显得尤为重要。就以上两种改变变量值的情形来说,第二种情形比较直观,即方法何时调用,便何时改变相应变量值。当然,其中的特殊方法——构造器除外。构造器可以认为是一种特殊的初始化过程,但由于其特殊性,其初始化过程又必须单独考虑。

本文主要以包括“构造器”在内的一些初始化操作对变量值改变的先后顺序为线索,进行了一些代码实验和思考。

由于该主题的情况较复杂,笔者打算先从几个点出发,讨论变量值改变的先后顺序,最后再将这些点中的情况进行一个统一的讨论。

一、先初始化静态(static)变量,再初始化非静态变量。

其中涉及到类的加载机制,因为静态变量是在类加载的过程中便开辟空间,而非静态变量在实例化对象的时候才会开辟空间,具体代码实验如下:

class A
{
	int y=printInit("non-static");
	static int x= printInit("static");

	private static int printInit(String s)
	{
		System.out.println(s);
		return 1;
	}
}



class InitSequStatic 
{
	public static void main(String[] args)
	{
		A a= new A();
	}
}




其运行结果如下:

Java类中的变量什么时候初始化_初始化



可以发现,尽管A类中的非静态变量先于静态变量定义,但在初始化的过程中(准确来说是类的加载和对象的实例化过程中),静态变量先于非静态变量。这一点,我们在类继承中将会理解得更加清楚


二、对于有类继承关系的代码中,先初始化(加载)父类静态变量,然后初始化(加载)子类静态变量,继而初始化父类非静态变量,调用父类构造器,最后初始化子类非静态变量,调用子类构造器。

若存在多重继承关系,也同理。之所以此处静态变量“初始化”后面的括号中有“加载”一词,是因为静态变量在类加载的过程中首先会进行默认初始化,但非静态变量在对象实例化的过程中就不会进行默认初始化。此处需要提及:初始化分为默认初始化、显示初始化、构造代码块初始化和构造函数初始化,这将在第三点“初始化过程”中具体提及。

以下图为例:


先依次初始化(加载)A类、B类和C类的静态变量,再依次初始化A类的非静态变量,调用A类的构造器;然后依次初始化B类的非静态变量,调用B类的构造器;最后依次初始化C类的非静态变量,调用C类的构造器。具体代码实验如下:

class A 
{
	A()
	{
		System.out.println("A constructor");
	}
	static int ax=printInit("A static");

	int ay=printInit("A nontatic");

	private static int printInit(String s)
	{
		System.out.println(s);
		return 1;
	}
}
 class B extends A
 {
	 B()
	{
		System.out.println("B constructor");
	}
	static int bx=printInit("B static");

	int by=printInit("B nontatic");

	private static int printInit(String s)
	{
		System.out.println(s);
		return 1;
	}
 }

 class C extends B
 {
	 C()
	{
		System.out.println("C constructor");
	}
	static int cx=printInit("C static");

	int cy=printInit("C nontatic");

	private static int printInit(String s)
	{
		System.out.println(s);
		return 1;
	}

	public static void main(String[] args)
	 {
		C c=new C();
	}
 }

其运行结果如下:

Java类中的变量什么时候初始化_Java类中的变量什么时候初始化_02