Java flow control

Can someone explain why this code gives output as null? When I try to call new A() instead of new B() , it prints the current date.

 class A { Date d = new Date(); public A() { printDate(); } void printDate() { System.out.println("parent"); System.out.println(d); } } class B extends A { Date d = new Date(); public B() { super(); } @Override void printDate() { System.out.println("child"); System.out.println(d); } } public class Test { public static void main(String[] args) { new B(); } } 
+5
source share
5 answers

After all the inputs, I hope the following answer will satisfy,

Since B also has a field d, Ad is not inherited to B, where B has its own copy of d.

So, when the control is in B.printDate (), it tries to find Ad (because the function is called from A).

this works fine if i delete the next line from B

 Date d = new Date(); 
+1
source

new B () calls constructor B, which calls constructor A. The constructor calls printDate() , which, because of the redefinition, executes B printDate() , which prints the value of the variable d B However, the variable d B is not yet initialized (it will be initialized only after the execution of constructor A). Therefore, it is still null (this is the default value for reference variables).

On the other hand, when you instantiate A ( new A() ), printDate of A is printDate , and it prints the variable d A , which was initialized earlier to the executable constructor A

If this is not clear, Bd does not override Ad, it just hides it. Only methods can be overridden.

+4
source

Declare Date as Static

 static Date d = new Date(); public B(){ super(); } @Override void printDate(){ System.out.println("child"); System.out.println(d); } 
+1
source

When you create an instance of B :

  • constructor B chains to constructor A

  • constructor A calls printDate , but this is B.printDate override called

  • B.printDate prints Bd .

  • which gives null because the Bd field was not initialized

  • returns printMethod , and constructor A returns

  • fields B initialized by setting Bd to a nonzero value. But its too late to influence the way out.


Some lessons to learn from this:

  • It is a bad idea for a constructor to call an instance method on the object that it creates if this instance method is not private or final . If you manage to call a method that has been overloaded with a subclass, then this method will see the instance variables of the subclass before they are initialized ... and this is problematic.

  • It is a bad idea to use the same name for a non-file field in a class and subclass. Both fields will exist, and it might be difficult for someone reading the code to keep it in mind.

  • Non-personal instance fields are a bad idea. They are harmful to encapsulation.

+1
source

This is because when you call super (), the Date d variable defined in class A is initialized. Since in class B the variable d is an object variable, and it overwrites the variable d from the parent class, and the object variables are built only after the this pointer is constructed, you get zero. If you want this to work as expected, make the variable d in class B a static variable, which will then be initialized by loading the classes.

+1
source

Source: https://habr.com/ru/post/1207202/


All Articles