浅谈 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、父类>子类
二、静态变量和静态代码块只加载一次,因为它们是全局共享的
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对象的初始化顺序
- JAVA--浅谈实例化对象时的初始化顺序
- 浅谈 java对象的初始化【2012年7月25日 小冬分享】
- 浅谈 java对象的初始化【2012年7月25日 小冬分享】
- 浅谈 Objective-C 下对象的初始化
- 浅谈java对象转json,数字精确出现丢失问题
- 解析Java类和对象的初始化过程
- 解析Java类和对象的初始化过程
- Java创建对象的初始化顺序(转载)
- Java一个对象的初始化过程
- My_Java之笔记(3)-对象初始化顺序
- JAVA对象数组的初始化方法
- java进行对象初始化的过程
- java类和对象的初始化
- 深入理解Java对象的创建过程:类的初始化与实例化
- 黑马程序员--03.Java面向对象--05.子类对象初始化的过程【个人总结】
- Java:对象创建和初始化过程
- Java基础知识-对象初始化
- 黑马程序员:Java对象的初始化过程
- Java对象初始化大全