`

剖析一个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对象初始化顺序.pdf

    以下是一个示例代码,用于演示 Java 对象初始化顺序的问题: ```java class Guest { public Guest() { System.out.println("Guest"); } } class Dad extends Guest { public Dad() { System.out.println("Dad...

    详解Spring 中如何控制2个bean中的初始化顺序

    在 Spring 框架中,控制多个 bean 的初始化顺序是一个常见的问题。本篇文章将详细介绍如何控制 2 个 bean 的初始化顺序,提供了多种实现方式,并分析了每种方式的优缺。 问题场景 在实际开发中,我们经常会遇到...

    java代码的初始化顺序demo

    这个"java代码的初始化顺序demo"显然旨在演示这一过程。让我们深入探讨Java中的初始化顺序及其背后的机制。 1. **类加载阶段**: 在Java程序运行时,JVM会先加载类的字节码文件(.class文件)。这个过程包括加载、...

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

    这个文件名称表明它包含一个Java源代码文件,该文件可能用于演示静态和对象初始化块的概念。通过查看和分析这个文件的源代码,我们可以更深入地理解这两种初始化块的工作原理和应用场景。 总之,理解并有效地使用...

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

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

    java中类的初始化顺序

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

    java类中静态域、块,非静态域、块,构造函数的初始化顺序

    ### Java 类中静态域、块,非静态域、块,构造函数的初始化顺序 #### 一、概述 在 Java 编程语言中,类的初始化顺序对于理解程序的行为至关重要。特别是当涉及到静态域(静态变量)、非静态域(实例变量)、静态块...

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

    在这个例子中,我们有一个名为`Test`的类,它包含了一个`int`类型的字段`i`,一个对象初始化块(非静态代码块),一个构造函数,以及一个静态代码块。下面是这个类的详细结构: ```java public class Test { int i...

    类初始化顺序示例讲解

    ### 类初始化顺序详解 本文将基于给定的Java示例代码深入探讨类初始化的顺序问题。这不仅是Java语言的关键特性之一,在其他面向对象语言(如C++、.NET)中也有相似的概念。理解这一概念有助于程序员更好地掌握面向...

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

    在Java编程语言中,理解成员变量的初始化顺序对于正确地设计和实现类结构至关重要。通过本实验,我们将深入了解成员变量的初始化顺序,以及如何通过实际代码示例来验证这些概念。 #### 实验步骤解析 ##### 步骤一...

    Java类初始化顺序

    Java类的初始化顺序是编程中一个非常重要的概念,它涉及到对象的创建过程和成员变量的初始化。当一个Java类被实例化或者其静态成员被访问时,类的初始化过程就开始了。以下详细解释了Java类的初始化顺序: 1. **...

    java代码初始化流程研究

    静态变量的初始化顺序按照它们在源代码中的出现顺序进行,而静态块则是在类加载时按顺序执行的。例如,在`JvmTest.java`和`JvmTest1.java`中,如果有静态变量和静态初始化块,它们的执行顺序将体现在`<clinit>`方法...

    类和对象的初始化过程.zip

    在`Test.java`中,可能展示了这种初始化顺序。 总结,这个压缩包文件提供了关于Java中类和对象初始化的实例,包括静态和非静态成员的处理、继承、构造函数的调用顺序等。通过分析并运行这些代码,开发者可以更深入...

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

    在本文中,我们将详细介绍Java类继承关系中的初始化顺序,并通过实例形式对比分析Java非继承关系中的初始化与继承关系中的初始化相关原理与操作技巧。 首先,让我们来了解Java类继承关系中的初始化顺序。在Java中,...

    深入java虚拟机加载初始化

    这个结果与我们的直觉相悖,其背后的原因在于JVM的初始化顺序。 当类被加载时,JVM会按照如下顺序执行: 1. **类加载**:将类加载到内存中。 2. **连接**:包括验证、准备和解析阶段。 3. **初始化**:在这个阶段...

    Java类的基本运行顺序

    本文将详细解析Java类的基本运行顺序,包括加载、初始化、执行等阶段,以及相关工具的运用。 首先,我们从类的生命周期开始。一个Java类的生命周期可以分为以下几个阶段: 1. **加载(Loading)**:当Java虚拟机...

    学习java静态数据初始化.doc

    - 合理安排静态成员和非静态成员的初始化顺序,确保程序逻辑的正确性。 通过本篇文章的学习,我们了解了Java中静态初始化的基本概念、执行过程以及如何正确地在程序中使用静态初始化。这对于理解和优化Java应用...

    通过Java字节码发现有趣的内幕之初始化篇(下)Java开

    比如,我们可以通过合理地安排初始化顺序,优化代码结构,避免不必要的资源消耗。此外,对于一些复杂的并发场景,理解初始化过程可以帮助我们预防潜在的线程安全问题。 总的来说,Java字节码的深入研究能够使开发者...

    Java static静态初始快

    4. **多线程环境**:如果多个线程同时加载同一个类,静态初始化块会被同步执行,确保线程安全。这意味着多个线程不会同时执行同一类的静态初始化块。 5. **继承关系**:子类会继承父类的静态初始化块,但不会重复...

    java内存对象分配过程研究

    本文通过对Java虚拟机内存区域的分析,详细介绍了对象创建的过程,包括定义对象变量、为对象分配内存以及初始化对象等关键步骤。此外,还探讨了对象在内存中的具体布局以及初始化过程中的一些细节。希望本文能够帮助...

Global site tag (gtag.js) - Google Analytics