So, we continue the excursion into the Java-problems. Another of the same sources, however, it may seem very simple for experienced or for those who have a compiler at hand.

Code:

public class A { public A() { myMethod(); } public void myMethod() { Date date = new Date(); } } public class B extends A { private Date date = new Date(); public B() { date = new Date(); } @Override public void myMethod() { System.out.println(date); } //... public static void main(String[] args) { B sub = new B(); sub.myMethod(); } } 

Questions:

  1. What is the output of this program?
  2. Explain your previous answer

For OOP learners, the task will be very useful. In addition, you can add your thoughts on why this program is not fail-safe (robust).

  • one
    When I was going to answer the question, I remembered that Bloch was discussing a similar situation in his book "Effective Java". I looked there - and there is almost an identical example :) In general, I recommend to all programmers who already have some experience, the book is excellent. - yozh
  • It seems to me that it will be clearer to use certain strings instead of indefinite Date instances (the values ​​of which depend on the execution time of the program): in each place of interest to us the program has its own string, the value of which is known before the execution of the program. Then it will be convenient to answer the question "what is the output of this program?", Citing as a response the line (s), rather than poking a finger into the code: the program will display the date (s), which (s) will be instantiated there and there. - Nikolay Artamonov
  • Only having a weak idea of ​​how it works correctly, you will push on, perhaps, NOT the correct idea of ​​a novice programmer. That is why it is called that dates with the same name are determined both in one and in another class, which can be confusing, which means it will give more value to understanding the situation. - Dex

2 answers 2

I admit immediately, the answer is obtained using the compiler.

 null Tue Oct 11 00:19:35 MSD 2011 

The thing is that the A myMethod () called from the constructor turns out to be the constructor method of the same name B, and at this time the date field of class B has not yet been initialized with a date. It is clear that the memory is allocated and reset. The second line of output is the expected result of calling sub.myMethod () from main ().

The order of calls is: constructor A, from it a method myMethod () of class B (it overrides myMethod () of class A), constructor B (initializes the date) and finally sub.myMethod ();

The local for class A method myMethod () is not called at all. The @Override directive does not manifest itself in this case (the signatures are the same).

Apparently this is an example of not having to do methods with the same names (not just signatures!) Called from constructors. Yes, Java is the language in which puzzles are elegantly written.

  • Glad you liked it again. But the task is an exam, no computer. Allocated only 20 minutes. To understand and answer three questions (in writing). I will wait with acceptance, maybe someone else will say a few words about robust. - Dex
  • Hope to say. The level I have is not the one that would be without a computer, dry. - avp
  • @Dex, this is an example of what I had in mind. Using dates, it is not clear from this answer exactly which date the program displays: 1) the one that is instantiated in the initializer of the date field of class B, 2) which is instantiated in the constructor B, or 3) which is instantiated in the A # myMethod method. It is necessary to clearly indicate this in the answer. If there were lines instead of dates, then this would no longer be necessary. The program would give a more sensible conclusion: null I'm from constructor of B - Nikolay Artamonov
  • You were not required to write the exact date, etc. The question boils down to this. On the exam, the answer is:> null> Date was correct. The main thing is to clarify what is going on. It is also more important to explain why the program is not fault-tolerant, about which I would ask you to speak out, instead of discussing the subject of the assignment that I present as-is , that is, how I received, I give it in the same form. - Dex
  • 2
    "Apparently, this is an example of not having to do methods with the same name (not just signatures!) Called from constructors." - no, this is an example of what can happen if you call an override method from a constructor. Sometimes this is just what you need, but usually not. - cy6erGn0m

In addition to answering avp

Initializing a class state by calling an override method is a potential threat to mis-initialize the parent class, and, as a result, the unpredictable work of the derived class.

In addition, a non-initialized instance may leak through this due to its transfer to other objects and / or streams from the overridden method.

  • I did not quite understand the phrase Initializing the state of a class by calling the override method , i.e. override and not call? - Dex
  • I meant that if a class method is designed to be overridden by heirs, then you should not call it from the constructor. But the phrase "redefine and not call" I no longer understood. - a_gura
  • I did not fully understand, you are proposing to override the method, but not to use it, or what you said. - Dex
  • I do not propose anything :) I merely point out that it is not safe to call methods intended for redefining from the constructor. - a_gura
  • And I just clarified because I did not understand :) Thank you! - Dex