`

剖析一个java对象初始化顺序问题

    博客分类:
  • JVM
阅读更多
剖析一个java对象初始化顺序问题
今天我在Dzone阅读了一篇关于java对象实例初始化顺序的有趣文章。说它有趣,是因为作者使用了一种并不太推荐的编码风格,只有用这种编码风格才能触发这个极为少见的 Java object initialization order 问题。

其实java对象初始化顺序算是一个比较基础的java知识点。但是网上的文章多半描述不清,使用上一不小心就容易出问题。
所以在本文中,我想结合JLS和自己的理解,举例剖析问题的所在。

OK,我们先来看个模仿Dzone作者原意的简单例子:


package com.kenwublog.tmp;

public class A extends B {
public int a = 100;

public A() {
super();
System.out.println(a);
a = 200;
}

public static void main(String[] args) {
System.out.println(new A().a);
}
}

class B {
public B() {
System.out.println(((A) this).a);
}
}
例子代码很简单,不多做解释了,直接看输出:

0
100
200
对照这个输出,我们来详细分析一下对象的初始化顺序:
1,为A类分配内存空间,初始化所有成员变量为默认值,包括primitive类型(int=0,boolean=false,…)和Reference类型。
2,调用A类构造函数。
3,调用B类构造函数。
4,调用Object空构造函数。(java编译器会默认加此构造函数,且object构造函数是个空函数,所以立即返回)
5,初始化B类成员变量,因为B类没有成员变量,跳过。
6,执行sysout输出子类A的成员变量小a。// 此时为0
7,初始化A类成员变量,将A类成员变量小a赋值100。
8,执行sysout输出当前A类的成员变量小a。// 此时为100
9,赋值当前A类的成员变量小a为200。
10,main函数中执行sysout,输出A类实例的成员变量小a。// 此时为200

加粗的那两行描述是重点,结论是成员变量初始化是在父类构造函数调用完后,在此之前,成员变量的值均是默认值。
Dzone作者就是栽在这里,没有仔细分析成员变量初始化在对象初始化中的顺序,造成了程序未按原意执行。
其实这类问题,熟悉原理是一方面,本质上只要不在构造函数中插入过多的业务逻辑,出问题的概率也会低很多。
分享到:
评论

相关推荐

    通过java字节码分析学习对象初始化顺序

    今天用了jmock对进行单元测试编码,发现一个比较奇怪的语法,static使用方法,见下面例子

    java父类和子类初始化顺序的深入理解

    本篇文章是对java父类和子类初始化顺序进行了详细的分析介绍,需要的朋友参考下

    Java类继承关系中的初始化顺序实例详解

    主要介绍了Java类继承关系中的初始化顺序,结合实例形式详细对比分析了Java非继承关系中的初始化与继承关系中的初始化相关原理与操作技巧,需要的朋友可以参考下

    浅谈Java变量的初始化顺序详解

    本篇文章是对Java变量的初始化顺序进行了详细的分析介绍,需要的朋友参考下

    Java-objects-initial.rar_objects

    分析java对象初始化顺序,对于java初学者来说非常有用。

    java面试题静态加载顺序构造方法

    5.所以一个输出结果为tttt,没问题了吧。 6.X类的static语句块执行完了,就该执行main()方法啦。 7.new Z();此方法被执行。 8.既然new Z();那么Z类就要被加载。因为Z类继承X类。所以必须先加载X类才行。因为X类...

    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入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    对Java语言的每个语法都提供了一个或多个例程讲解 大量使用流程图表示程序的执行过程,使用结构图表示程序的内部状态 每章最后都给出了典型的练习题,让读者及时练习,巩固提高,并提供了参考答案 目录 第1篇 ...

    java 编程入门思考

    2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档标记 2.8.7 方法文档标记 2.8.8 文档示例 2.9 编码样式 2.10 ...

    Java初学者入门教学

    2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档标记 2.8.7 方法文档标记 2.8.8 文档示例 2.9 编码样式 2.10 ...

    java 面试题 总结

    面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性: 多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多...

    java联想(中文)

    2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档标记 2.8.7 方法文档标记 2.8.8 文档示例 2.9 编码样式 2.10 ...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    对Java语言的每个语法都提供了一个或多个例程讲解 大量使用流程图表示程序的执行过程,使用结构图表示程序的内部状态 每章最后都给出了典型的练习题,让读者及时练习,巩固提高,并提供了参考答案 目录 第1篇 ...

    疯狂JAVA讲义

    学生提问:我们只是创建了一个Ostrich对象时,哪来的Bird对象? 147 5.6.4 调用父类构造器 148 学生提问:为什么我创建Java对象时从未感觉到java.lang.Object的构造器被调用过? 150 5.7 多态 151 5.7.1 多态性 ...

    JAVA_Thinking in Java

    2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档标记 2.8.7 方法文档标记 2.8.8 文档示例 2.9 编码样式 2.10 ...

    Thinking in Java简体中文(全)

    2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入HTML 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档标记 2.8.7 方法文档标记 2.8.8 文档示例 2.9 编码样式 2.10 ...

    JAVA基础课程讲义

    一个典型的JAVA程序的编写和运行过程 19 第一个程序常见错误 20 第一个JAVA程序的总结和提升 20 常用Java开发工具 20 常用dos命令 21 本章笔试作业 21 本章上机操作 21 第二章(1) 编程的基本概念 22 注释 22 标识符 ...

    Thinking in Java 中文第四版+习题答案

    2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档标记 2.8.7 方法文档标记 2.8.8 文档示例 2.9 编码样式 2.10 总结...

    超爽的自学课件(java)

    在这一章的最后,我们将更贴近地观察初始化过程:自动成员初始化、指定成员初始化、初始化的顺序、static(静态)初始化以及数组初始化等等。 <br>(5) 第5章:隐藏实现过程 本章要探讨将代码封装到一起的方式...

    超级有影响力霸气的Java面试题大全文档

    面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性:  多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化...

Global site tag (gtag.js) - Google Analytics