您的位置:首页 > 职场人生

一个让98%java程序员犯难的问题的思考

2010-01-16 15:47 435 查看
源代码:

public class Parent
{
protected void test() {}

public Parent()
{
this.test();
}

public static void main(String[] args)
{
new Child();
}
}

class Child extends Parent
{
private int instanceValue = 1;
public void test()
{
System.out.println("instance value is: " + instanceValue);
}
}
--------------------------------------------

此程序的输出结果为instance value is:0,可能很多人(包括很多老程序员)都会想当然得以为输出结果为1,或者不会有输出,或者认为这个程序本身就是错的(我的老师就是这么认为的,呵呵~)

看了很多有关这个问题的讨论,现在提出一点我的见解:

分析:这个问题首先涉及的知识是类加载分为三个过程:装载、链接、初始化,有关这个知识我在之前的帖子“类加载分为三个过程:装载、链接、初始化”中有专门提到过,而真正了解这个知识的人并不多,所以才有了如标题所说的结果~

OK,现在我们来开始一步步分析:首先加载class文件,对类中的变量进行内存分配(声明),此时instance是实例变量,加载的时候并不会对其进行真正的初始化(即不会把1赋给它,它只会得到系统给它的默认值0,这是问题的关键)。

接下来就要执行main方法体了,ok,它里面只有一条语句,new一个子类对象,调用子类默认构造器的时候要先调用父类的无参构造器,父类构造器这时会调用父类的test方法,根据多态原理,该test方法将会被子类的test覆盖,子类方法将会打印一条语句,而此时instance变量并未被初始化,故打印的结果为0.这里的this.test()方法调用可能不是很好理解,因为它已经用this表明调用父类方法,此时它是不知道子类已经覆盖了父类的这个方法,关于这一点,目前还找不到解释的方法,姑且把它理解为多态机制吧。

好了,现在我们把程序稍微改动一下,就是把private int instanceValue = 1;改为private static int instanceValue = 1;此时输出的结果就为1了,因为将instance声明为类变量后,在类被加载的时候就已经对其进行初始化了,关于这一点,在之前的帖子“类加载分为三个过程:装载、链接、初始化”有详细说明。

事实上这个源程序一点都不难,到为什么有那么多人会得出错误的结论呢,主要原因就是对原理机制不是很了解,而这个应该在我们以后的学习中引起足够的重视,现在很多公司笔试面试的时候都会涉及诸如这样的细节,所以从现在开始我们就要做好准备了,呵呵
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: