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

posted @ 2011-06-23 21:53  华仔崽  阅读(479)  评论(1编辑  收藏  举报
友情链接 JeffreyZhao  zhangziqiu 短信猫 MVC学习 .net面试问答(大汇总) python