请问下如何解释这段 Java 程序第一次输出时 I have $0? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Newyorkcity
V2EX    问与答

请问下如何解释这段 Java 程序第一次输出时 I have $0?

  •  
  •   Newyorkcity 2021 年 7 月 28 日 2284 次点击
    这是一个创建于 1638 天前的主题,其中的信息可能已经有所发展或是发生改变。
    public class Main { static class Father { private int mOney= 1; public Father() { this.mOney= 2; this.showMoney(); } public void showMoney() { System.out.println("I am father, I have $" + this.money + "."); } } static class Son extends Father { private int mOney= 3; public Son() { this.mOney= 4; this.showMoney(); } @Override public void showMoney() { System.out.println("I am son, I have $" + this.money + "."); } } public static void main(String[] args) { final Son son = new Son(); System.out.println("I am son, I have $" + son.money + "."); } } 

    输出结果

    I am son, I have $0. I am son, I have $4. I am son, I have $4. 

    后面两行我都能理解,但是第一次输出时为什么 money 字段是 0 ?

    谢谢

    12 条回复    2021-07-28 19:12:44 +08:00
    Hurriance
        1
    Hurriance  
       2021 年 7 月 28 日   3
    执行子类的初始化函数的时候,先会去执行父类的初始化函数,其中就会执行 showMoney(),其实父类、子类也有 showMoney(),但是因为你是子类调用栈过来的,所以直接调用子类的 showMoney(),但是此时子类的 money 还没初始化,默认值为 0,即输出 0
    qping
        2
    qping  
       2021 年 7 月 28 日   4
    先初始化父亲, 调用了 showMoney() , showMoney 方法被子类重写了, 调用的是儿子的 showMoney , 儿子的 money 还没赋值,所以是 0
    zhangshine
        3
    zhangshine  
       2021 年 7 月 28 日
    搜索“Java 类的初始化顺序”
    AlkTTT
        4
    AlkTTT  
       2021 年 7 月 28 日
    你这两个类都是静态的,
    执行顺序为: 父类构造方法 -> 父类 showMoney -> 子类重写了 showMoney,所以调用子类的 showMoney(此时子类的参数还没执行构造方法,money 为 0)
    dinghmcn
        5
    dinghmcn  
       2021 年 7 月 28 日
    如果子类没有重写 showMoney()输出的是什么?
    Aruforce
        6
    Aruforce  
       2021 年 7 月 28 日
    尽管 Son 和 Father 都有 money 。。但这是两个 money 。。。

    第一个输出的 money 是在 Father 类初始化时尚未初始化的 Son 的 money...

    而这个值应该是 0 虽然你直觉可能觉得是 3...

    在 Father 的初始话代码执行的时候... 实际上 son 的 mOney=3 尚未执行。。所以默认值 0
    NeroKamin
        7
    NeroKamin  
       2021 年 7 月 28 日
    第一个 money 是执行 Father 构造方法时打印的 Son 类实例中的 money 字段,此时其值为初始零值
    des
        8
    des  
       2021 年 7 月 28 日 via iPhone
    @Aruforce 这个确实是反直觉,除非说是分配成员变量空间和初始化赋值是分两步做的,而且可以被打断,是这样的吗?
    admol
        9
    admol  
       2021 年 7 月 28 日
    在父类的构造方法、showMoney 方法、子类的构造方法、showMoney 方法里面分别打上断点,可以观察到执行输出顺序;
    songkaizong
        10
    songkaizong  
       2021 年 7 月 28 日   3
    这道题出自《深入理解 Java 虚拟机》 8.3 小节。
    为了加深理解,笔者又编撰了一份“劣质面试题式”的代码片段,请阅读代码清单 8-10,思考运行后会输出什么结果。
    输出两句都是“I am Son”,这是因为 Son 类在创建的时候,首先隐式调用了 Father 的构造函数,而
    Father 构造函数中对 showMeTheMoney()的调用是一次虚方法调用,实际执行的版本是
    Son::showMeTheMoney()方法,所以输出的是“I am Son”,这点经过前面的分析相信读者是没有疑问的
    了。而这时候虽然父类的 money 字段已经被初始化成 2 了,但 Son::showMeTheMoney()方法中访问的却
    是子类的 money 字段,这时候结果自然还是 0,因为它要到子类的构造函数执行时才会被初始化。
    Cusmate
        11
    Cusmate  
       2021 年 7 月 28 日 via Android
    楼主所有发的帖子都是在问问题,而且挺频繁的。
    Newyorkcity
        12
    Newyorkcity  
    OP
       2021 年 7 月 28 日
    @Hurriance
    @qping
    @songkaizong

    =2 的那个 this 是谁?是 Father 实例,那接下来那个 showMoney 的调用者也应该是 Father 实例,它却用了重写的函数?那为啥字段赋值的时候它不用重写的字段?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3795 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 05:09 PVG 13:09 LAX 21:09 JFK 00:09
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86