`

zz java 类初始化顺序

    博客分类:
  • Java
 
阅读更多
zz from http://ig2net.info/archives/321.html

我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是(静态变量、静态初始化块)>(变量、初始化 块)>构造器。我们也可以通过下面的测试代码来验证这一点:
Java代码

    public class InitialOrderTest { 
    
        // 静态变量 
        public static String staticField = " 静态变量"; 
        // 变量 
        public String field = "变量"; 
    
        // 静态初始化块 
        static { 
            System.out.println(staticField); 
            System.out.println("静态初始化块"); 
        } 
    
        // 初始化块 
        { 
            System.out.println(field); 
            System.out.println("初始 化块"); 
        } 
    
        // 构造器 
        public InitialOrderTest() { 
            System.out.println("构造 器"); 
        } 
    
        public static void main(String[] args) { 
            new InitialOrderTest(); 
        } 
    }

运行以上代码,我们会得到如下的输出结果:

    静态变量
    静态初始化块
    变量
    初始化块
    构造器

这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:
Java代码 复制代码

    class Parent { 
        // 静态变量 
        public static String p_StaticField = "父类–静态变量"; 
        // 变量 
        public String p_Field = "父类–变量"; 
    
        // 静态初始化块 
        static { 
            System.out.println(p_StaticField); 
            System.out.println("父类–静态初始化块"); 
        } 
    
        // 初始化块 
        { 
            System.out.println(p_Field); 
            System.out.println("父类 –初始化块"); 
        } 
    
        // 构造器 
        public Parent() { 
            System.out.println("父类 –构造器"); 
        } 
    } 
    
    public class SubClass extends Parent { 
        // 静态变量 
        public static String s_StaticField = "子类–静态变量"; 
        // 变量 
        public String s_Field = "子类–变量"; 
        // 静态初始化块 
        static { 
            System.out.println(s_StaticField); 
            System.out.println("子类–静态初始化块"); 
        } 
        // 初始化块 
        { 
            System.out.println(s_Field); 
            System.out.println("子类 –初始化块"); 
        } 
    
        // 构造器 
        public SubClass() { 
            System.out.println("子类 –构造器"); 
        } 
    
        // 程序入口 
        public static void main(String[] args) { 
            new SubClass(); 
        } 
    } 

运行一下上面的代码,结果马上呈现在我们的眼前:

    父类–静态变量
    父类–静态初始化块
    子类–静态变量
    子类–静态初始化块
    父类–变量
    父类–初始化块
    父类–构造器
    子类–变量
    子类–初始化块
    子类–构造器

现在,结果已经不言自明了。大家可能会注意到一点,那就是,并不是父类完全初始化完毕后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化 是在父类的变量、初始化块和构造器初始化之前就完成了。

那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了 呢?实际上这取决于它们在类中出现的先后顺序。我们以静态变量和静态初始化块为例来进行说明。

同样,我们还是写一个类来进行测试:
Java代码

    public class TestOrder { 
        // 静态变量 
        public static TestA a = new TestA(); 
         
        // 静态初始化块 
        static { 
            System.out.println("静态 初始化块"); 
        } 
         
        // 静态变量 
        public static TestB b = new TestB(); 
    
        public static void main(String[] args) { 
            new TestOrder(); 
        } 
    } 
    
    class TestA { 
        public TestA() { 
            System.out.println("Test–A"); 
        } 
    } 
    
    class TestB { 
        public TestB() { 
            System.out.println("Test–B"); 
        } 
    }

运行上面的代码,会得到如下的结果:

    Test–A
    静态初始化块
    Test–B

这也不要太纠结。
下面的写法会产生递归。
public class A
{
static{
a = new A("static block");
}
final static A a;
static A aa = new A("static init");
// A ma = new A("inner init");//这里在实例化变量时又实例自己的对象,递归
{
new A("inner block");//这里在实例化变量时又实例自己的对象,递归
}
public A()
{
// TODO Auto-generated constructor stub
}
public A(String i)
{
System.out.println(i);
}
public static void main(String[] args)
{

}
}

这里顺便温习一下构造函数的继承问题:

创建一个子类的对象实例的时候,必先调用父类的无参数的构造函数(默认构造函数),假如父类有带参数的构造函数,那么系统将不会给它创建无参数的构造函数,这时,子类在实例化的时候,因为找不到父类的默认构造函数,编译器将会报错,但如果在子类的构造函数中指定用父类的带参数的构造函数的时候,或者在父类中加一个无参数的构造函数,就不会报错。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics