`
329937021
  • 浏览: 124467 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

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

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

相关推荐

    java面试题-类的初始化顺序.doc

    这个顺序表明,无论类之间的继承关系如何,初始化顺序始终是:静态变量和静态初始化块先于非静态成员。在创建对象时,父类的初始化先于子类。这是Java语言规范所规定的,确保在子类访问父类的静态或非静态成员时,...

    Java类继承初始化顺序

    当我们谈论“Java类继承初始化顺序”时,涉及到的关键知识点包括构造器、成员变量的初始化、super关键字以及方法的覆盖。 首先,了解类初始化的顺序至关重要。当创建一个子类实例时,初始化过程遵循以下步骤: 1. ...

    类继承的初始化顺序类,继承的初始化顺序

    在面向对象语言中(如Java、C#等),当创建一个继承自某个基类的子类对象时,会有一个特定的初始化顺序。这个顺序通常遵循以下步骤: 1. **基类静态成员初始化**:如果基类中有任何静态成员,则会在程序启动时按照...

    JAVA类的初始化顺序文.pdf

    面试中经常出现这类问题,旨在考察开发者对于内存分配、对象创建以及类加载过程的理解。理解这些顺序有助于编写更健壮、更易于维护的代码。 需要注意的是,如果父类中有参数化的构造器,而在子类中没有显式调用它,...

    java代码的初始化顺序demo

    总之,Java代码的初始化顺序是类加载的必然过程,涉及到静态和实例初始化块、构造函数、成员变量初始化以及继承关系的影响。这个demo是学习和理解这些概念的重要工具,通过实际操作可以加深对Java内存管理和对象生命...

    java中类的初始化顺序

    ### Java中类的初始化顺序详解 #### 一、概述 在Java编程语言中,类的初始化是一个非常重要的概念。类的初始化涉及到多个方面,包括静态成员变量、实例成员变量、静态初始化块、实例初始化块以及构造函数等。本文...

    java对象的初始化顺序[参考].pdf

    Java对象的初始化顺序是一个关键的编程概念,它涉及到类加载、静态初始化、实例初始化等多个步骤。下面我们将详细探讨这些步骤。 首先,当程序运行并创建一个新的对象时,JVM(Java虚拟机)会按照特定的顺序来初始...

    Java初始化顺序1

    Java 初始化顺序详解 在 Java 中,变量可以分为两类:类变量(静态变量)和实例变量(对象变量)。类变量是使用 static 关键字修饰的变量,它们属于类,而不是对象。实例变量则是没有使用 static 关键字修饰的变量...

    Java静态初始化块和对象初始化块

    总之,理解并有效地使用静态和对象初始化块是Java开发中的关键技能,它们可以帮助我们更好地控制类和对象的初始化过程,确保代码的高效性和正确性。在实际编程中,我们应该根据需求谨慎选择合适的初始化策略,以优化...

    Java初始化块Java初始化块.doc

    Java 初始化块,也称为构造代码块,是Java编程语言中的一种特性,用于在对象创建时执行特定的初始化操作。初始化块在类的定义中以 `{}` 包裹的一段代码,没有返回值,也不需要任何参数。根据是否带有 `static` ...

    JAVA面试题解惑系列——类的初始化顺序

    在Java中,类的初始化顺序是一个经常被问及的面试题目,尤其对于Java程序员和工程师来说,了解这个知识点是必须的。在Java中,类的初始化顺序是面试中的经典问题之一,它涉及到继承、静态成员以及实例成员等多个方面...

    Java中对象初始化顺序的详细介绍

    这种情况下,初始化顺序如下:首先,`Lower`类的实例创建并分配默认值,然后调用`Upper`的构造器,接着执行`Initializer.initialize()`,该方法根据对象的实际类型(`Lower`)来设置字段的值。 5. **默认值**:即使...

    成员的初始化顺序和多态性

    ##### 步骤一:成员初始化顺序 成员变量的初始化顺序遵循以下规则: 1. **实例变量的初始化**:按照它们在类中出现的顺序进行初始化。 2. **构造函数中的初始化**:在构造函数内部,可以显式初始化成员变量,这...

    JAVA面试题解惑系列(一)——类的初始化顺序-JAVA程序员JAVA工程师面试必看.pdf

    在Java编程世界中,类的初始化顺序是理解面向对象编程概念的一个重要方面。尤其对于那些准备应对技术面试的Java程序员和工程师来说,掌握这一知识点是面试时的必备能力之一。本文将深入探讨Java中类的初始化顺序,...

    java面向对象编程--课堂笔记

    在Java中,构造方法是一个特殊的方法,它的任务是初始化新创建的对象。构造方法的名称必须与类名相同,且没有返回值。当使用`new`关键字创建对象时,构造方法会被自动调用。例如: ```java Student s = new Student...

    JAVA面试题解惑系列

    在Java面试过程中,经常会出现关于类初始化顺序的问题。这些问题不仅考察面试者对于Java基础知识的理解程度,还能够揭示出他们对于语言特性的深入掌握。本文将通过具体实例详细解析Java中类的初始化顺序,特别是针对...

    Java变量初始化

    Java 变量初始化的时机是指在 Java 语言中变量的初始化过程,包括变量的声明、初始化和赋值的步骤。 Java 变量声明 在 Java 语言中,每个变量必须先声明,然后才能使用。声明变量时必须指定该变量的数据类型。...

    java解惑分析

    ### Java中的类初始化顺序详解 #### 一、引言 在Java编程中,类的初始化顺序是一个非常重要的概念,尤其对于那些深入理解Java语言特性的开发者来说更是如此。本篇文章将详细探讨Java中不同类型的成员(包括静态成员...

Global site tag (gtag.js) - Google Analytics