About Question enthuware.ocajp.i.v7.2.1337 :

Moderator: admin

ETS User

About Question enthuware.ocajp.i.v7.2.1337 :

Post by ETS User » Sun Aug 26, 2012 11:34 pm

Hi, got a bit confused here. I read in a book -

"Instance members are accessible only after the super constructor runs."

Then why is it that upon calling the print( ) method of class A, (which in fact is B's print( ) due to polymorphism), the method was able to access the uninitialized instance variable i of B even though the constructor of A has not yet finished executing?

What am I not understanding right?

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Mon Aug 27, 2012 4:45 am

The initialized value of the instance member is visible after the code that initializes it executes. So for example, if you are setting an instance member in an instance block, you will see that value after that block executes. But if you are setting a value in the constructor, then in an instance block you will see the default value (i.e. 0 for primitives, null for Objects, and false for booleans).

You can access the instance members before explicit initialization because they are always initialized to default values first.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

ETS User

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by ETS User » Mon Aug 27, 2012 7:58 am

Thanks for the explanation Paul.

To sum it up, the instance members of a class can actually be accessed even if its super constructor is still running - it's just that value is not yet initialized.

To quote from a review book -
"Instance variables are accessible only after the super constructor runs."
This is why I am confused.

Or maybe the author of that book just misstated that one?

gustavomzina
Posts: 1
Joined: Sat Dec 06, 2014 7:49 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by gustavomzina » Fri Dec 12, 2014 11:27 am

I understand that instance members are initialized after the super() method call within B class constructor. But why does the code below outputs 4, 4?

Code: Select all

class A{
	A() {  print();   }
	void print() { System.out.println("A"); }
}
public class B extends A{
	final int i =   4;
	public static void main(String[] args){
		A a = new Teste();
		a.print();
	}
	void print() { System.out.println(i); }
}
Final members are not instance members?

Thanks.

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Fri Dec 12, 2014 9:21 pm

Final member can certainly be an instance member (like the one you have in your code). I tried searching the JLS for information on when final instance fields are initialized but couldn't find any. Apparently, a final field is assigned a value even before the constructor or instance initializers are run.
Unfortunately, Section 12.4.2 of JLS doesn't say anything about the situation that you've shown.

-Paul.
If you like our products and services, please help us by posting your review here.

coder007
Posts: 25
Joined: Wed Dec 17, 2014 9:29 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by coder007 » Sun Dec 21, 2014 3:18 pm

I don't understand your note:
This happens because the method print() is non-private, hence polymorphic.
If I make A's print() method private, code event doesn't compile.
Can we say that we can't override private methods of super class, nor even overload it?

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Sun Dec 21, 2014 8:03 pm

Private methods are not inherited and therefore cannot be overridden. You can still have a method with the same signature (i.e. same name and same parameters) in a subclass though. But it will not override the super class's method.

You can certainly have a method with the same name and different parameters in the subclass. But again, it is technically overloading the private method of the base class for the same reason that it is not inherited in the subclass.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

dmcinnis1
Posts: 16
Joined: Wed Feb 25, 2015 8:52 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by dmcinnis1 » Wed Mar 11, 2015 8:03 pm

Hi,

I understand overriding and run-time polymorphism (or thought I did). I don't understand why A's print isn't used instead of B's print since A is created first and B hasn't been created yet. How does A know about B's print if B doesn't exist yet? What am I missing?

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Wed Mar 11, 2015 9:09 pm

Since the actual class of the object referred to by the variable a is B and since print method in A is overridden by B, B's version of print method is executed.
Why do you think B doesn't exist yet? Class B exists, instance of b also exists but not initialized. The method definition is part of the class, not of the object.
If you like our products and services, please help us by posting your review here.

dmcinnis1
Posts: 16
Joined: Wed Feb 25, 2015 8:52 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by dmcinnis1 » Sat Mar 14, 2015 3:36 pm

Hi,

I meant to say "b hasn't been created yet." What I mean is that I do understand the run time polymorphism rule that the method of the object type is invoked. I got the second part of the answer that "4" is printed as the second value. What I don't understand is the sequence of events between the 2 statements:

A a = new B();
a.print();

In new B(), A's constructor is called in B by an implicit super(). I'm visualizing that in creating the b object, the A part of it gets created first, then the b part is created. So I'm confused that A's constructor is calling b's print instead of it's own print. I don't understand why b's print is called here if it hasn't even finished creating the A and the B parts of b. I'm obviously way off base here. Help!

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Sat Mar 14, 2015 9:17 pm

That is just the way the language is designed to work. It may look weird but there is nothing special going on there to understand.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

AristPhil
Posts: 4
Joined: Wed Jan 06, 2016 5:38 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by AristPhil » Fri Jan 15, 2016 8:59 am

Can I explain the reason, why the value 4 has not been assigned to variable i when the superconstructor calls the overridden print() method, like this?
I. All instance variables are initialized with their default values when their class is loaded. Thus, i is initialized with 0, when class B is loaded.
II. The actual initialization with concrete values happens in this order:

1. all static initializer blocks and static variables are initialized down the class hierarchy, i.e. from the uppermost superclass first down to the calling subclass last - in our mock question there are no static block or variable at all;

2. all instance initializer blocks and instance variables of the uppermost superclass are initialized (in whatever order they appear in the code) - in our mock question we don't have such.

3. the constructor of the uppermost superclass is initialized - in our mock question this is class' A no-arg constructor that calls the overridden print() method of (sub)class B:
Since class' B instance variables have only been assigned to default values so far (here i=0;), 0 is printed to the console. This is, why we see 0 instead of 4!

4. all instance initializer blocks and instance variables of the second uppermost superclass are initialized - as in our mock question there is only one superclass A, we've just arrive at our base class B: NOW i is set to 4 - but not printed out yet!

5. the constructor of the second uppermost superclass is initialized - again we arrive at the base class B and its default constructor. NOW main() calls the overridden print() method which prints 4 to the console.

Summary: As step 4 has not run by the time the superconstructor calls the overridden print() method, which at this point can only return the default value of 0 for variable i, we get an console output of 0 4 instead of 4 4.

Step 1 is executed first upon class loading for all classes. After that the instance initialization and constructor execution is done together per class down the class hierarchy - (NOT instance initialization of all classes followed by constructor execution of all classes)! This is why i has not been set to 4 but is still 0 when the superconstructor calls the overridden print() method.

(For simplicity, I omitted the exact execution flow due to constructor chaining; it does not matter here).

P.S. Luckily I found a good example in the JSL: http://docs.oracle.com/javase/specs/jls ... l#jls-12.5 (Example 12.5-1. Evaluation of Instance Creation); explained in lucid terms!
Last edited by AristPhil on Fri Jan 15, 2016 10:17 am, edited 1 time in total.

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Fri Jan 15, 2016 9:23 am

AristPhil wrote:Can I explain the reason, why the value 4 has not been assigned to variable i when the superconstructor calls the overridden print() method, like this?
...
You got it :)
If you like our products and services, please help us by posting your review here.

eddie3
Posts: 14
Joined: Sat Dec 17, 2016 10:17 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by eddie3 » Mon Dec 19, 2016 2:54 pm

Shouldn't the code prints 0, 4, 4? There is no constructor in class B, so a default constructor that calls super( ) is automatically inserted in class B. Therefore, when A a = new B( ); is executed, first Java calls the no-arg constructor in A (which prints 0), then calls the automatically inserted no-arg constructor in B(which prints 4 because a constructor is the last step of all initialization process). And at last a.print( ) will print 4. So the code will print 0,4,4?

To test it out, I compiled a simplified code in Java,

Code: Select all

class A{
    public A(){System.out.println("A");}
}

class B extends A{
    public B(){System.out.println("B");}

    public static void main(String[] args){
    A object = new B();
    }
}
And it prints

Code: Select all

A
B

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Mon Dec 19, 2016 9:33 pm

Not sure what you mean by the bold part in, "...then calls the automatically inserted no-arg constructor in B (which prints 4 because a constructor is the last step of all initialization process). Why do you think the default constructor that is automatically inserted will have a print statement in it?
Paul.
If you like our products and services, please help us by posting your review here.

eddie3
Posts: 14
Joined: Sat Dec 17, 2016 10:17 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by eddie3 » Tue Dec 20, 2016 12:46 am

Because the default constructor in class B will call the super( ) as its first statement, and in the case of this question, since A is the super class of B, shouldn't the the no-argument constructor in class A, which contains the body, {print( )}, be called?

Also, what I mean in the bold line is that when a class is initialized, the static fields and block will run first, then instance fields and blocks, and at last the constructor. Therefore, int i will have already been given a value of 4 before the default constructor in class B is called. And the default constructor in class B call super( ), which calls the overriding print( ) method in class B, and prints out i, which is 4.

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Tue Dec 20, 2016 12:57 am

Your post tells me that you have not fully understood the flow of execution of constructors and initializers. When you do new B(), the default constructor of B is invoked, which, in turn calls super(). Now, in the given code, class B does not have an explicitly defined constructor. The default one that is provided by the compiler only contains a call to super(). It does not contain any print statements. Therefore, when the call to super() executes, A's constructor will be invoked, which contains a call to print(i). This call will print 0 at this time because i hasn't yet been assigned the value of 4. Execution control will then return back to the default constructor of B, which has no further statements.
Finally, the line a.print() from main will be executed, which will print 4 because by this time i has been initialized to 4.

That's it. There is no third print statement anywhere.

I will suggest you to read about this from a book or try running various code variations.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

eddie3
Posts: 14
Joined: Sat Dec 17, 2016 10:17 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by eddie3 » Tue Dec 20, 2016 3:18 am

Oh, I get it now. So this line "A a = new B( );" will actually call B's no-argument constructor instead of A's. I misunderstood because of this sentence in the explanation: "Here,when an object of class B is created, first A's constructor is called." I thought this means that "A a= new B( );" will call A's constructor instead of B's. Now I understand that this will actually call B's constructor, but in the case of this question calling B's constructor is calling A's constructor, because of the lack of an explicit constructor in B's. Thank you for the clarification!

dxie1154
Posts: 9
Joined: Sat Jan 14, 2017 5:01 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by dxie1154 » Tue Mar 14, 2017 8:21 pm

Hi,

I don't really understand the part on how B's print() method is executed.
From how I saw it, I had thought that it would call A's print() because it is in the A class, and the constructor that calls the print() method is in the A class as well.
But now it says it will call B's print() so I am really confused on this.
Can you tell me why it will call B's print()?

Thanks in advance.

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Tue Mar 14, 2017 9:48 pm

Note that print is a non-private instance method and is therefore polymorphic, which means, the selection of the method to be executed depends on the class of actual object on which it is invoked. Here, since the class of actual object is B, B's print is selected instead of A's print.
If you like our products and services, please help us by posting your review here.

Chandu
Posts: 7
Joined: Thu Mar 30, 2017 7:15 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by Chandu » Thu Jun 08, 2017 3:07 am

Code: Select all

class A{
   A() {  print();   }
   void print() { System.out.println("A"); }
}
class B extends A{
   int i =   4;
   public static void main(String[] args){
      A a = new B();
      a.print();
   }
   void print() { System.out.println(i); }
}
What will be the output when class B is run ?

Explanation: Note that method print() is overridden in class B. Due to polymorphism, the method to be executed is selected depending on the class of the actual object. Here, when an object of class B is created, first B's default constructor (which is not visible in the code but is automatically provided by the compiler because B does not define any constructor explicitly) is called. The first line of this constructor is a call to super(), which invokes A's constructor. A's constructor in turn calls print(). Now, print is a non-private instance method and is therefore polymorphic, which means, the selection of the method to be executed depends on the class of actual object on which it is invoked. Here, since the class of actual object is B, B's print is selected instead of A's print. At this point of time, variable i has not been initialized (because we are still in the middle of initializing A), so its default value i.e. 0 is printed.   Finally, 4 is printed. 
Query-------------// in this i got a doubt that if value of "i" isnt initialized at that point of time then how come its assigning the default int value for that variable? i mean if the control doesnt go to that line of code during that particular time of execution then how come compiler knows the data type of that variable and assigns the default value for it?

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Thu Jun 08, 2017 4:33 am

1. This is about execution. There is no compiler involved in execution. It is the JVM.
2. When an object is created, the first thing JVM does is allocate space for that object. This space includes space for its instance variables. This space that is used for instance variables is all filled with zeros. This is the default value of all kinds of variables. If the variable is a primitive it is 0, if it is a boolean the value is interpreted as false, and if the variable is a reference variable, it is interpreted as null.
3. After the JVM allocates space for an object, it executes the initializers, and constructors.

The value that is being talked about in this question is the value that is there in that space after memory allocation and before execution of any initializers/constructors.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

shambhavi
Posts: 25
Joined: Fri Aug 04, 2017 12:21 am
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by shambhavi » Wed Aug 09, 2017 2:08 am

gustavomzina wrote:I understand that instance members are initialized after the super() method call within B class constructor. But why does the code below outputs 4, 4?

Code: Select all

class A{
	A() {  print();   }
	void print() { System.out.println("A"); }
}
public class B extends A{
	final int i =   4;
	public static void main(String[] args){
		A a = new Teste();
		a.print();
	}
	void print() { System.out.println(i); }
}
Final members are not instance members?

Thanks.
Final fields are instance members but they are not always given a default value ! try it out as illustrated in the explanations below !
int i; will compile but
final int i; // will not compile if you haven't initialized it anywhere in the constructor too

since in your code you have given final int i=4; this is a compile time constant whose value is known at compile time itself and hence, when this variable is created at run time it will be assigned this value itself rather than a default value because anyways its a constant and its value will not change in the rest of the program !

but observe in the below code : output is :
0
4

Code: Select all

class A{
	A() {  print();   }
	void print() { System.out.println("A"); }
}
 public class B extends A {
    
final int i;
B()
{
    i=4;
}

   void print() { System.out.println(i); } 
     
           
  public static void main(String[] args) { 
    
  A a = new B();
		a.print();
 
      System.out.println();
      
      
 }
 }
here a default value is given since its value is not known at compile time and 4 is assigned only after its first useage !

Angi000
Posts: 3
Joined: Sun Jan 28, 2018 12:44 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by Angi000 » Sun Jan 28, 2018 2:50 pm

Hi Paul,

I don't understand why the default value of 'i' is used when creating the object 'a' is referring to. So 0, not 4. Please help.

Thanks

admin
Site Admin
Posts: 8558
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocajp.i.v7.2.1337 :

Post by admin » Sun Jan 28, 2018 10:09 pm

When you do new B(), the JVM has to initialize the memory space for an object of class B. Included in B are the instance fields defined in A as well. So when the JVM tries to initialize B, it has to first initialize the instance members of A. While initializing the fields of A, the JVM encounters a print statement that tries to print the value of i. But at this time, i has not been initialized fully (because B's constructor hasn't run yet), so the print statement prints the default value assigned by the JVM i.e. 0.
If you like our products and services, please help us by posting your review here.

Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests