Perplexing output in Java with inheritance and overriding methods

梦想与她 提交于 2019-11-28 11:50:48
Idos

There are a few facts you ought to know before I start explaining every single step in your code's execution:

  • Field references are resolved based on reference type and method calls are resolved during run-time (in a dynamic-fashion) based on the object type.
  • super() is placed implicitly in every constructor even if you don't put it there yourself (it is not called if you call super(int x, int y) for instance).
  • It is considered very bad practice to call "override-able" methods from a constructor - you will see why when we go through the execution.

Now let's break down your code step-by-step:

  • You instantiate B by calling its default constructor B().
  • As I said before, the call to super() is added implicitly to any constructor, so A() is immediately called.
  • Inside A() you call foo(), which is overridden in class B and that is why foo() is called from B.
  • Inside B's foo() you get the output B.foo(): bar = null since Java didn't get to initialize B's fields yet (its constructor hasn't been executed yet!) and the fields of object type are initialized to null by default.
  • Now that we are done with the constructor of A() we go back to the constructor of B().
  • Inside said constructor, we have the call to foo() again, which is again B's foo(). But different from last time, B have its fields initialized (after the call to super()) properly so you get the expected B.foo(): bar = B.bar.
  • Now we are back to the warm embrace of main.
  • You access a.bar, and since as I said field references are resolved based on reference type, you get the field bar of A.
  • Lastly, for the same reason, you call a.foo() which again triggers B's foo() which prints b.bar once again.

And we are done! :)

Further references and worthwhile reading materials:
Static and dynamic binding explained
Order of constructor calls

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!