当前位置:编程学习 > JAVA >>

浅谈 java对象的初始化

java对象的初始化
小冬(珠海)11:02:48
我们知道一个对象可以有静态变量、变量、静态初始化块、初始化块,当我们创建一个对象时,它是怎么初始化的呢?按什么顺序初始化的呢?
 
public class Test {
 
    
    // 静态变量
    public static String staticField = "静态变量"; // 变量
    public String field = "变量";
    // 静态初始化块
    static {
        System.out.println(staticField);
        System.out.println("静态初始化块");
    }
    // 初始化块
    {
        System.out.println(field);
        System.out.println("初始化块");
    }
    // 构造器
    public Test() {
        System.out.println("构造器");
    }
    public static void main(String[] args) {
        Test test = new Test();
 
    }
}
 
运行下代码,输出结果是:
静态变量
静态初始化块
变量
初始化块
构造器
 
 
由此可以看到,当new一个对象时,它并不是就是调构造方法,而是先初始化属性变量,我们把变量的定义先后顺序换下,再执行,会发现,静态的是先于非静态进行实始化的,那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢?
我们先改下代码:
 
public class Test {
 
    public static TestA ta = new TestA();
    // 静态变量
    public static String staticField = "静态变量"; // 变量
    public String field = "变量";
    // 静态初始化块
    static {
        System.out.println(staticField);
        System.out.println("静态初始化块");
    }
    // 初始化块
    {
        System.out.println(field);
        System.out.println("初始化块");
    }
    // 构造器
    public Test() {
        System.out.println("构造器");
    }
    public static void main(String[] args) {
        Test test = new Test();
 
    }
}
 
class TestA {
    public TestA() {
        System.out.println("Test--A");
    }
}
 输出是:
Test--A
静态变量
静态初始化块
变量
初始化块
构造器
 
 
静态变量:static TestA ta = new TestA()在静态初始化块前,所以先输出Test--A
再换下位置,把static TestA ta = new TestA()放到在静态初始化块后,我们发现输出是:
静态变量
静态初始化块
Test--A
变量
初始化块
构造器
 
 
由此可见这是取决于它们在类中出现的先后顺序,同理可得:变量和初始化块之间也如此,总结可得:初始化优先级是(静态变量/静态初始化块)>(变量/初始化块)>构造器。
 
 
那继承关系时的初始化又是怎样的呢?如下:
大家应该知道,初始化子类时会先初始化父类,再看代码:
 
public class Test extends Parent{
    // 静态变量
    public static String staticField = "子类静态变量"; // 变量
    public String field = "子类变量";
    // 静态初始化块
    static {
        System.out.println(staticField);
        System.out.println("子类静态初始化块");
    }
    //public static TestA ta = new TestA();
    // 初始化块
    {
        System.out.println(field);
        System.out.println("子类初始化块");
    }
    // 构造器
    public Test() {
        System.out.println("子类构造器");
    }
    public static void main(String[] args) {
        Test test = new Test();
    }
}
 
class Parent{
 
    public String field = "父类变量";// 变量
    public static String staticField = "父类静态变量"; // 静态变量
    // 静态初始化块
    static {
        System.out.println(staticField);
        System.out.println("父类静态初始化块");
    }
    // 初始化块
    {
        System.out.println(field);
        System.out.println("父类初始化块");
    }
    // 构造器
    public Parent() {
        System.out.println("父类构造器");
    }   
}
刚才结果应该是:
父类静态变量
父类静态初始化块
子类静态变量
子类静态初始化块
父类变量
父类初始化块
父类构造器
子类变量
子类初始化块
子类构造器
 
从结果看到,并不是父类完全初始化完后再进行子类的初始化,子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。
 
我们在main方法再创建一个对象,Test test2 = new Test();
大家就test2的初始化又如何?
 
为了好看,我们子类构造器里加多行代码System.out.println("***********");
输出结果:
父类静态变量
父类静态初始化块
子类静态变量
子类静态初始化块
父类变量
父类初始化块
父类构造器
子类变量
子类初始化块
子类构造器
***********
父类变量
父类初始化块
父类构造器
子类变量
子类初始化块
子类构造器
***********

发现什么了?
静态变量和静态代码块只加载一次 。
 
 
总结:
一、初始化优先级:
1、静态变量/静态初始化块)>(变量/初始化块)>构造器
2、父类>子类

二、静态变量和静态代码块只加载一次,因为它们是全局共享的
 

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,