您的位置:首页 > 编程语言 > Java开发

浅谈 java对象的初始化

2013-03-07 10:19 253 查看
我们知道一个对象可以有静态变量、变量、静态初始化块、初始化块,当我们创建一个对象时,它是怎么初始化的呢?按什么顺序初始化的呢?

 
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、父类>子类

二、静态变量和静态代码块只加载一次,因为它们是全局共享的 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: