`
miman2008
  • 浏览: 37711 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Java对象创建过程-成员初始化顺序 (转)

阅读更多

前几天开始重读《Java编程思想(第3版)》,对Java对象的创建过程、成员初始化顺序(尤其是涉及到组合和继承的情况下)作一下梳理总结。
书中第4章初始化与清理中对Java对象的创建过程总结如下:
假设有个名为Dog的类

当首次创建型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件。
然后载入Dog.class(这将创建一个Class对象),有关静态初始化的动作都会执行。因此,静态初始化只在Class对象首次加载的时候进行一次。
当你用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
这块存储空间会被清零,这就自动地将Dog中的所有基本类型数据设置成了默认值(对数字来说就是0,对布尔型和字符型也相同),而引用则被置成了null。
执行所有出现于域定义处的初始化动作。
执行构造器。
没有涉及到继承的时候,这个过程描述已经很清晰了,那么如果涉及到继承呢,看下面一段示例代码:
Java代码

Java代码 复制代码
  1. // Mouse4j.java      
  2. package com.mouse4j.simpletest;      
  3. // 静态字段类      
  4. class StaticField {      
  5.     private String s;      
  6.     StaticField(String s) {      
  7.         this.s = s;      
  8.         System.out.println("I am static field " + s);      
  9.     }       
  10. }      
  11. // 与静态字段相对的普通字段      
  12. class NormalField {      
  13.     private String s;      
  14.     NormalField(String s) {      
  15.         this.s= s;      
  16.         System.out.println("I am mormal field " + s);      
  17.     }      
  18. }      
  19. // 特点类      
  20. class Characteristic {      
  21.     private String s;      
  22.     Characteristic(String s) {      
  23.         this.s = s;      
  24.         System.out.println("Creating Characteristic " + s);      
  25.     }       
  26. }      
  27. // 描述类      
  28. class Description {      
  29.     // 注释1:在此例中如果用于组合的类中也包含static字段      
  30.     // public static StaticField dStr = new StaticField("Description");      
  31.           
  32.     // 注释2:在此例中如果用于组合的类中也包含在域定义处初始化      
  33.     // private NormalField dStr1 = new NormalField("Description");      
  34.     private String s;      
  35.     Description(String s) {      
  36.         this.s = s;      
  37.         System.out.println("Creating Description " + s);      
  38.     }       
  39. }      
  40. class Animal {      
  41.     public static StaticField AnimalStr = new StaticField("Animal");      
  42.     private Characteristic c = new Characteristic("Animal Characteristic");      
  43.     private Description d = new Description("Animal Description");      
  44.     Animal() {      
  45.         System.out.println("Animal()");      
  46.     }      
  47. }      
  48. class Mouse extends Animal{      
  49.     public static StaticField MouseStr = new StaticField("Mouse");      
  50.     private Characteristic c = new Characteristic("Mouse Characteristic");      
  51.     private Description d = new Description("Mouse Description");      
  52.     Mouse() {      
  53.         System.out.println("Mouse()");      
  54.     }      
  55. }      
  56. public class Mouse4j extends Mouse{      
  57.     public static StaticField Mouse4jStr = new StaticField("Mouse4j");      
  58.     private Characteristic c = new Characteristic("Mouse4j Characteristic");      
  59.     private Description d = new Description("Mouse4j Description");      
  60.     Mouse4j() {      
  61.         System.out.println("Mouse4j()");      
  62.     }      
  63.      
  64.     public static void main(String[] args) {      
  65.         new Mouse4j();      
  66.     }      
  67.      
  68. }    
// Mouse4j.java   
package com.mouse4j.simpletest;   
// 静态字段类   
class StaticField {   
    private String s;   
    StaticField(String s) {   
        this.s = s;   
        System.out.println("I am static field " + s);   
    }    
}   
// 与静态字段相对的普通字段   
class NormalField {   
    private String s;   
    NormalField(String s) {   
        this.s= s;   
        System.out.println("I am mormal field " + s);   
    }   
}   
// 特点类   
class Characteristic {   
    private String s;   
    Characteristic(String s) {   
        this.s = s;   
        System.out.println("Creating Characteristic " + s);   
    }    
}   
// 描述类   
class Description {   
    // 注释1:在此例中如果用于组合的类中也包含static字段   
    // public static StaticField dStr = new StaticField("Description");   
       
    // 注释2:在此例中如果用于组合的类中也包含在域定义处初始化   
    // private NormalField dStr1 = new NormalField("Description");   
    private String s;   
    Description(String s) {   
        this.s = s;   
        System.out.println("Creating Description " + s);   
    }    
}   
class Animal {   
    public static StaticField AnimalStr = new StaticField("Animal");   
    private Characteristic c = new Characteristic("Animal Characteristic");   
    private Description d = new Description("Animal Description");   
    Animal() {   
        System.out.println("Animal()");   
    }   
}   
class Mouse extends Animal{   
    public static StaticField MouseStr = new StaticField("Mouse");   
    private Characteristic c = new Characteristic("Mouse Characteristic");   
    private Description d = new Description("Mouse Description");   
    Mouse() {   
        System.out.println("Mouse()");   
    }   
}   
public class Mouse4j extends Mouse{   
    public static StaticField Mouse4jStr = new StaticField("Mouse4j");   
    private Characteristic c = new Characteristic("Mouse4j Characteristic");   
    private Description d = new Description("Mouse4j Description");   
    Mouse4j() {   
        System.out.println("Mouse4j()");   
    }   
  
    public static void main(String[] args) {   
        new Mouse4j();   
    }   
  
}  


程序执行输出如下:

Console 写道

Java代码 复制代码
  1. I am static field Animal    
  2. I am static field Mouse    
  3. I am static field Mouse4j    
  4. Creating Characteristic Animal Characteristic    
  5. Creating Description Animal Description    
  6. Animal()    
  7. Creating Characteristic Mouse Characteristic    
  8. Creating Description Mouse Description    
  9. Mouse()    
  10. Creating Characteristic Mouse4j Characteristic    
  11. Creating Description Mouse4j Description    
  12. Mouse4j()   
I am static field Animal 
I am static field Mouse 
I am static field Mouse4j 
Creating Characteristic Animal Characteristic 
Creating Description Animal Description 
Animal() 
Creating Characteristic Mouse Characteristic 
Creating Description Mouse Description 
Mouse() 
Creating Characteristic Mouse4j Characteristic 
Creating Description Mouse4j Description 
Mouse4j() 




从程序输出可以看出:

当首次创建型为Mouse4j的对象时,Java解释器查找类路径,定位Mouse4j.class文件。
Java解释器会根据Mouse4j.class定位其基类Mouse.class、再根据Mouse.class定位到基类Animal.class文件,有关静态初始化的动作从基类到子类依次执行。
当你用new Mouse4j()创建对象的时候,首先将在堆上为Mouse4j对象(包括其基类Mouse和Animal中的域)分配足够的存储空间。
这块存储空间会被清零,这就自动地将Mouse4j中的所有基本类型数据(包括其基类Mouse和Animal中的)设置成了默认值(对数字来说就是0,对布尔型和字符型也相同),而引用(包括其基类Mouse和Animal中的)则被置成了null。
执行基类Animal中所有出现于域定义处的初始化动作。
执行基类Animal构造器。
执行基类Mouse中所有出现于域定义处的初始化动作。
执行基类Mouse构造器。
执行子类Mouse4j中所有出现于域定义处的初始化动作。
执行子类Mouse4j构造器。
第5~10步过程总结如下:
在为所创建对象的存储空间清零后,找到继承链中最上层的基类,执行a、b两步:
a.执行其出现在域定义处的初始化动作
b.然后再执行其构造器
然后从基类到子类依次执行这两步操作。

到这里,涉及到继承Java对象创建过程和成员初始化顺序就理清楚了~(《编程思想》中关于这一点的描述让我有点晕~还是用程序实践一下思路会比较清晰)
再看组合的情况,将程序代码中的注释1和注释2去掉,考虑用于组合的类Description中也包含static字段和在域定义处初始化的情况,程序执行结果如下:

Console 写道

Java代码 复制代码
  1. I am static field Animal    
  2. I am static field Mouse    
  3. I am static field Mouse4j    
  4. Creating Characteristic Animal Characteristic    
  5. I am static field Description    
  6. I am mormal field Description    
  7. Creating Description Animal Description    
  8. Animal()    
  9. Creating Characteristic Mouse Characteristic    
  10. I am mormal field Description    
  11. Creating Description Mouse Description    
  12. Mouse()    
  13. Creating Characteristic Mouse4j Characteristic    
  14. I am mormal field Description    
  15. Creating Description Mouse4j Description    
  16. Mouse4j()   
I am static field Animal 
I am static field Mouse 
I am static field Mouse4j 
Creating Characteristic Animal Characteristic 
I am static field Description 
I am mormal field Description 
Creating Description Animal Description 
Animal() 
Creating Characteristic Mouse Characteristic 
I am mormal field Description 
Creating Description Mouse Description 
Mouse() 
Creating Characteristic Mouse4j Characteristic 
I am mormal field Description 
Creating Description Mouse4j Description 
Mouse4j() 




可见Description对象的创建过程与成员初始化顺序与本文开头的Dog对象的例子一致。(The End)

对原文作者表示感谢!

http://329937021.iteye.com/blog/546885

分享到:
评论

相关推荐

    Java开发者文档,分享日常学习的一些小知识点 .rar

     ※在所有类成员初始化完成之后,才调用本类的构造方法创建对象。  构造方法的作用就是初始化。  (2) 静态对象的初始化  程序中主类的静态变量会在main方法执行前初始化。  不仅第一次创建对象时,类中的...

    Thinking in java4(中文高清版)-java的'圣经'

    5.6.1 指定初始化 5.7 构造器初始化 5.7.1 初始化顺序 5.7.2. 静态数据的初始化 5.7.3. 显式的静态初始化 5.7.4. 非静态实例初始化 5.8 数组初始化 5.8.1 可变参数列表 5.9 枚举类型 5.10 总结 第6章 访问权限控制 ...

    Java 基础核心总结 +经典算法大全.rar

    类的初始化 成员初始化 构造器初始化初始化顺序 数组初始化 对象的销毁 对象作用域 this 和 super 访问控制权限继承 多态组合代理 向上转型static final 接口和抽象类接口 抽象类异常 认 识 Exception 什么是 ...

    Java开发技术大全(500个源代码).

    errorInit.java 演示变量初始化错误的程序 integerExample.java 演示各种整型变量的使用 isPrime.java 判断素数 leapYearByIf.java 用if语句判断闰年 leapYearByLogical.java 用逻辑表达式判断闰年 lowToUpper...

    java学习笔记 初学者必读

    5.3. 初始化数组 5-10 5.4. 多维数组 5-10 5.5. 数组拷贝 5-10 6. 五•对象和类 6-11 6.1. 面向对象与面向过程 6-11 6.2. 对象的概念 6-12 6.3. 成员变量和局部变量 6-12 6.4. 成员方法 6-12 6.5. This关键字 6-13 ...

    JAVA基础知识精华总结 收藏

    ※在所有类成员初始化完成之后,才调用本类的构造方法创建对象。 构造方法的作用就是初始化。 (2) 静态对象的初始化 程序中主类的静态变量会在main方法执行前初始化。 不仅第一次创建对象时,类中的所有静态变量...

    AIC的Java课程1-6章

     弄清构造函数和终结方法在继承层次结构中的调用顺序,强调子类必须调用超类的构造函数分配空间和初始化超类数据。  掌握方法重写(override)的基本要求。  理解和使用关键字final。  理解包的...

    疯狂JAVA讲义

    学生提问:构造器是创建Java对象的途径,是不是说构造器完全负责创建Java对象? 141 5.5.2 构造器的重载 142 学生提问:为什么要用this来调用另一个重载的构造器?我把另一个构造器里的代码复制、粘贴到这个构造器...

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    4.4 成员初始化 4.4.1 规定初始化 4.4.2 构建器初始化 4.5 数组初始化 4.5.1 多维数组 4.6 总结 4.7 练习 第5章 隐藏实施过程 5.1 包:库单元 5.1.1 创建独一无二的包名 5.1.2 自定义工具库 5.1.3 利用导入改变行为...

    corejavaNoteBook

    5.3. 初始化数组 5-10 5.4. 多维数组 5-10 5.5. 数组拷贝 5-10 6. 五•对象和类 6-11 6.1. 面向对象与面向过程 6-11 6.2. 对象的概念 6-12 6.3. 成员变量和局部变量 6-12 6.4. 成员方法 6-12 6.5. This关键字 6-13 ...

    java-servlet-api.doc

    Servlet引擎载入Servlet后,Servlet引擎必须对Servlet进行初始化,在这一过程中,你可以读取一些固定存储的数据、初始化JDBC的连接以及建立与其他资源的连接。 在初始化过程中,javax.servlet.Servlet接口的init()...

    Java 语言基础 —— 非常符合中国人习惯的Java基础教程手册

    创建对象包括声明、实例化和初始化三方面的内容。通常的格式为 : 1. 声明对象 对象声明实际上是给对象命名,也称定义一个实例变量。对象声明的一般格式为: type name 其中,type 是一个类的类名,用它声明的对象将...

    java 编程入门思考

    4.4 成员初始化 4.4.1 规定初始化 4.4.2 构建器初始化 4.5 数组初始化 4.5.1 多维数组 4.6 总结 4.7 练习 第5章 隐藏实施过程 5.1 包:库单元 5.1.1 创建独一无二的包名 5.1.2 自定义工具库 5.1.3 利用导入改变行为...

    Java入门教程(微学苑)-part1

    3.15 作为方法名来初始化对象 50 3.16 作为参数传递 51 3.17 Java方法重载 52 3.18 Java类的基本运行顺序 53 3.19 Java包装类、拆箱和装箱详解 54 3.20 包装类的应用 54 3.20.1.1 1) 实现 int 和 Integer 的相互转换...

    Java初学者入门教学

    4.4 成员初始化 4.4.1 规定初始化 4.4.2 构建器初始化 4.5 数组初始化 4.5.1 多维数组 4.6 总结 4.7 练习 第5章 隐藏实施过程 5.1 包:库单元 5.1.1 创建独一无二的包名 5.1.2 自定义工具库 5.1.3 利用导入改变行为...

    java面试800题

    "构造函数(constructor )在对象创建时初始化。 构造函数是和类同名的函数,没有返回类型,构造函数不能在普通的程序里面调用,只有当这个类被应用new实例化的时候才会被运行。构造函数没有返回类型,实际上,构造...

    java联想(中文)

    4.4 成员初始化 4.4.1 规定初始化 4.4.2 构建器初始化 4.5 数组初始化 4.5.1 多维数组 4.6 总结 4.7 练习 第5章 隐藏实施过程 5.1 包:库单元 5.1.1 创建独一无二的包名 5.1.2 自定义工具库 5.1.3 利用导入改变行为...

    编程思想下篇

    5.7.1 初始化顺序 5.7.2. 静态数据的初始化 5.7.3. 显式的静态初始化 5.7.4. 非静态实例初始化 5.8 数组初始化 5.8.1 可变参数列表 5.9 枚举类型 5.10 总结 第6章 访问权限控制 第7章 复用类 第8章 多态 第9章 接口 ...

    Thinking in Java(中文版 由yyc,spirit整理).chm

    4.4 成员初始化 4.4.1 规定初始化 4.4.2 构建器初始化 4.5 数组初始化 4.5.1 多维数组 4.6 总结 4.7 练习 第5章 隐藏实施过程 5.1 包:库单元 5.1.1 创建独一无二的包名 5.1.2 自定义工具库 5.1.3 利用导入改变行为...

    JAVA_Thinking in Java

    4.4 成员初始化 4.4.1 规定初始化 4.4.2 构建器初始化 4.5 数组初始化 4.5.1 多维数组 4.6 总结 4.7 练习 第5章 隐藏实施过程 5.1 包:库单元 5.1.1 创建独一无二的包名 5.1.2 自定义工具库 5.1.3 利用导入改变行为...

Global site tag (gtag.js) - Google Analytics