• java认证:剖析一个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作者就是栽在这里,没有仔细分析成员变量初始化在对象初始化中的顺序,造成了程序未按原意执行。

    其实这类问题,熟悉原理是一方面,本质上只要不在构造函数中插入过多的业务逻辑,出问题的概率也会低很多。

    转自:http://news.bangkaow.com/news/20110623/194720.html

  • 相关阅读:
    部分模块
    正则表达式和re模块
    软件开发的目录规范
    模块以及模块的导入
    迭代器、可迭代对象、迭代器对象、生成器、生成器表达式和相关的面试题
    内置方法补充
    递归、二分法、匿名函数和部分内置方法
    python的闭包和装饰器
    函数名本质、函数命名空间和作用域链
    函数简介和函数的结构分析
  • 原文地址:https://www.cnblogs.com/huazaizai/p/2088474.html
Copyright © 2020-2023  润新知