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

本文分析了一个Java程序,该程序包含父类调用子类重写方法的场景,并解释了为何实例变量未初始化前其值为0的现象。通过探讨类加载过程、变量初始化时机及多态原理,帮助读者理解Java构造器执行流程与类继承机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

源代码:

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声明为类变量后,在类被加载的时候就已经对其进行初始化了,关于这一点,在之前的帖子“类加载分为三个过程:装载、链接、初始化”有详细说明。

 

事实上这个源程序一点都不难,到为什么有那么多人会得出错误的结论呢,主要原因就是对原理机制不是很了解,而这个应该在我们以后的学习中引起足够的重视,现在很多公司笔试面试的时候都会涉及诸如这样的细节,所以从现在开始我们就要做好准备了,呵呵

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值