The code is like this :
class Base {
int x = 10;
public Base() {
this.printMessage();
x = 20;
}
public void printMessage() {
System.out.println("Base.x = " + x);
}
}
class Sub extends Base {
int x = 30;
public Sub() {
this.printMessage();
x = 40;
}
public void printMessage() {
System.out.println("Sub.x = " + x);
}
}
public class DispatchTest {
public static void main(String[] args) {
Base b = new Sub();
System.out.println(b.x);
}
}
The result is :
Sub.x = 0
Sub.x = 30
20
Can anybody please tell me how this code run?
Why doesn't the costructor of class Base run?
Because you created a new Sub object instance. The class Sub has the printMessage() method overriden, which means that the Base.printMethod() is not being executed.
The constructor of the Base class runs, but the this.printMessage() executes the printMessage method from the Sub class.
Immediatelly after the Sub's constructor has been invoked, the Base constructor is being called. It prints Sub.x = 0 because no x (in Sub) has been set so far. After that the value x gets assigned.
After the Base constructor is done, the rest of the Sub constructor is being executed. It prints calls the Sub's printMessage method again, but this time the value x has a value, and it prints Sub.x = 30.
The 20 comes from the System.out.println(b.x);.
You might wonder, why the value xis not assigned during the first printMessage call? Because you have x in your Sub class as well, so the x from the Base class is not visible!
Your SuperClass constructor is always called but "Polymorphic behaviour cannot be seen when accessing overridden member variables".
Base b = new Sub();
System.out.println(b.x);
Now if you access x(which is present in both subclass and superclass) it is actually the type of reference variable which determines the value.
Note: This behaviour is different with overridden methods,in this case it is actually the type of object which determines the method to be called not the type of reference variable.
The constructor
public Sub() {
this.printMessage();
x = 40;
}
is equivalent to
public Sub() {
super();
this.printMessage();
x = 40;
}
So when you create
Base b = new Sub();
Base's constructor gets executed followed by Sub's constructor. See JLS 8.8.7, which states
The first statement of a constructor body may be an explicit
invocation of another constructor of the same class or of the direct
superclass
Base's constructor is calling printMessage() which is overriden by Sub. When it gets called from Base's constructor printMessage() prints x of Sub which is not yet initialized. This is an anti pattern, so Sub.x = 0 gets printed (x is not yet initialized, and hence default value of int which is 0 )
Now once the Base's constructor finishes, Sub's constructor gets called and now the x is initialized to 30 why?
because
class Sub extends Base {
int x = 30;
public Sub() {
this.printMessage();
x = 40;
}
....
essentially means
class Sub extends Base {
int x;
public Sub() {
{
x=30;
}
this.printMessage();
x = 40;
}
....
hence this time printMessage() prints Sub.x = 30
finally 20 is printed because fields are NOT overriden.
When ever we are creating child class object then the following sequence of events will be executed automatically.
Step 1.Identification of instance members from parent to child and initialize them to default value.
after first step
Base instance variable is int x=0;
Sub instance variable is int x=0;
Step 2. Execution of instance variable assignments and instance blocks only in parent class
after second step
Base class instance variable is int x= 10;
Sub class instance variable is int x = 0;
Step 3.Execution of parent class constructor.
after third step
here you have a "printMessage()" invocation.It is overridden in child class Sub
So Sub class method is executes and prints Sub class's variable x value,which is now assigned as 0 only.
So the out put now "Sub.x = 0".
and Base class int x = 20;
Sub class int x = 0;
Step 4.Execution of instance variables and instance blocks in child class.
After 4th step
Base class int x=20;
Sub class int x=30;
Step 5.Execution of child constructor.
After 5th step.
In Sub class constructor you have "printMessage()" method invocation.So it will executes and prints output.
So the out put now "Sub.x = 30".
After the method invocation you have an assignment.
So now Base class int x=20;
Sub class int x=40;
For now your Sub class constructor created successfully.
Now you a print statement of variable x on type reference "Base".So now "Base" class variable x will be prints as output.
So the out put is "20".
Related
I am reading a Java text book and came across a doubt.
A reference variable of a superclass can be assigned a reference to an object of any subclass derived from that superclass. However, when a reference to a subclass object is assigned to a superclass reference variable, you will have access only to those parts of the object defined by the superclass.
Example:
class X {
int a;
X(int i) {
a = i;
}
}
class Y extends X {
int b;
Y(int i, int j) {
super(j);
b = i;
}
}
class SupSubRef {
public static void main(String args[]) {
X x = new X(10);
X x2;
Y y = new Y(5, 6);
x2 = x; // OK, both of same type
System.out.println("x2.a: " + x2.a);
x2 = y; // still Ok because Y is derived from X
System.out.println("x2.a: " + x2.a);
// X references know only about X members
x2.a = 19; // OK
// x2.b = 27; // Error, X doesn't have a b member
}
}
So, in the above example, x2 (a variable of the superclass type) can refer to an object of the derived class, bit it cannot access subclass specific members. However, in the discussion on method overriding, it is shown that a superclass reference variable's call to an overridden method can be resolved to the subclass method. But the subclass method is not defined in the superclass, so isn't this a contradiction, how is the superclass reference variable able to access the subclass specific method? Example:
class Sup {
void who() {
System.out.println("who() in Sup");
}
}
class Sub1 extends Sup {
void who() {
System.out.println("who() in Sub1");
}
}
class Sub2 extends Sup {
void who() {
System.out.println("who() in Sub2");
}
}
class DynDispDemo {
public static void main(String args[]) {
Sup superOb = new Sup();
Sub1 subOb1 = new Sub1();
Sub2 subOb2 = new Sub2();
Sup supRef;
supRef = superOb;
supRef.who();
supRef = subOb1;
supRef.who();
supRef = subOb2;
supRef.who();
}
}
The output from the program is shown here:
who() in Sup
who() in Sub1
who() in Sub2
So how is supRef able to access the who method in the subclass object?
When the textbook says that you can't access subclass-specific members with x2, it meant that you can't access them at compile time.
To the compiler. x2 is of type X (though it's really of type Y at runtime), so when the compiler sees you trying to access stuff defined in Y, it spots and says "that is not defined in X. You can't do that!"
However, we all know that at runtime, x2 stores a reference to a Y object. At runtime, you can indeed access members defined in Y with x2. You can prove this by using reflection.
At runtime, x2 is of type Y, so obviously Y's implementation will be called.
This question already has answers here:
How JVM loads parent classes in Java
(3 answers)
Closed 6 years ago.
In the following Java code, the Insect class is inherited by the Beetle class.
class Insect {
private int i = 9;
protected int j;
Insect() {
System.out.println("i = " + i + ", j = " + j);
j = 39;
}
private static int x1
= printInit("static Insect.x1 initialized");
static int printInit(String s) {
System.out.println(s);
return 47;
}
}
public class Beetle extends Insect {
private int k = printInit("Beetle.k initialized");
public Beetle() {
System.out.println("k = " + k);
System.out.println("j = " + j);
}
private static int x2
= printInit("static Beetle.x2 initialized");
public static void main(String[] args) {
System.out.println("Beetle constructor");
Beetle b = new Beetle();
}
}
The output is somehow comfusing.
static Insect.x1 initialized
static Beetle.x2 initialized
Beetle constructor
i = 9, j = 0
Beetle.k initialized
k = 47 j = 39
What is the order of initialization in this particular example?
Why is x2 initialized immediatly after x1? And why is the first line of the main method (System.out.println("Beetle constructor");), executed after x1 and x2 intializaton. So comfusing.
I know that the derived class constructor automatically calls the base class constructor (unless it has parameters and you'd use the super keyword). I know that variables are initialized before the constructor, and that static variables are initialized before other variables.
x1 and x2 are static. This means that they are initialized when the class is loaded. Since the main method is in Beetle, the class has to be loaded before invoking main. This is why x1 and x2 initialization is the first thing you see. Not sure about why the order of those two is as it is.
Now you are calling main and System.out.println("Beetle constructor"); is executed. Then it calls Beetle() which implicitly calls super() (aka Insect()) first. This prints i = 9, j = 0 because i is 9 and j has not been initialized at that point, which means it has the default int value 0.
Now j is set to 39 and the flow continues in Beetle(). This now initializes the fields of Beetle, in your case k. So when it comes to the explicit code in Beetle(), k is initialized to 47 and j to 39 by the super constructor.
This can be explained as follows -
Since static members are non-instance members i.e only one copy of the member is shared across all the instances of the class, these members are initialized first.
In this case, x1 is initialized first since its a static member present in the base class of the class where the main method is present.
Hence, 1st x1 is initialized.
Static member x2 in the subclass follows because of the same reason and also because there are no other static members present in Insect class.
Beetle constructor line is printed from the main method.
The constructors of the super class and sub class are called one after the other for obvious reasons
JVM(Class loader) loads Beetle class, when you invoke its main static method. After class loading, initialization of Beetle class takes place which means initializing all the static members of the class.
The base class is always initialized implicitly, thus you see the x1 initialized before x2.
You see the "Beetle constructor" printed after x1, and x2, because when you reference a static method of a class(as you are doing by calling main), the JVM order of execution jumps to initializing the class static members, before continuing with the execution of the main() method.
As an experiment, try removing the main method to another class,
public class Beetle1 {
public static void main(String[] args) {
System.out.println("Beetle1 constructor");
}
}
Now as the Beetle constructor is not referenced, the class loader does not load it, and you will see Beetle1 constructor printed.
I'm wondering what is happening here:
I have abstract superclass
public abstract class Superclass {
public Superclass()
{
doSth();
}
public abstract void doSth();
}
And subclass
public class Subclass extends Superclass{
private int x = 10;
public void doSth()
{
System.out.println("Value x="+this.x);
}
}
When I make
Subclass x= new Subclass();
x.doSth();
I get:
Value x=0
Value x=10
I don't know why first I get x=0 (why not x=10 from the start?) and then x=10?
The constructor of the super-class is executed before the isntance initializer expressions of the sub-class, which is why x still has the default value of 0 in the first call to doSth(). The second call x.doSth() takes places after the Subclass instance is fully initialized, so x contains 10.
More details :
When you call the constrcutor of Subclass, first it calls the constructor of Superclass which calls the constructor of Object. Then the body of the Superclass constructor is executed, so doSth() is executed. Only after the Superclass constructor is done, the instance initialization expressions of Subclass (in your case, the assignment x = 10; are evaluated. Before they are evaluated, x still contains the default value - 0, which is the value you see printed by the first call to doSth().
I have a Doubt
when we initialize our instance variables in Instance initialization block(s) in case of inheritance do they override the value of variable?
For example
class A{
int x;
}
class B extends A{
int x = 10;
}
public class C{
public static void main(String[] args){
A K = new B();
System.out.println(K.x);
}
}
o/p : 0
However when i use initialization blocks
class A{
int x;
{x = 15;}
}
class B extends A{
{x=20;}
}
public class C{
public static void main(String[] args){
A K = new B();
System.out.println(K.x);
}
}
OUTPUT 20
Why its so? why my initialization block(s) are affecting instance variables ? Moreover , i know that blocks are called when we make object but still the variable at output should correspond to variable type i.e A K (K should give value corresponding to class A)
You can override methods only, not variables. This code isn't "overriding" instance variables.
The first example has a different variables named x defined for A and B, making the variable an A means you see the variable defined for A (see the link provided by paulk23). In the second there is only one instance variable x which is visible to the subclass, the instance initializer assigns a value to an existing variable.
In the first example, you have two declarations of x, and in the second you only have one. In the second example, try changing B to:
class B extends A {
int x;
{ x=20; }
}
and you'll see the same behaviour as the first example: B defines a new variable that has an independent value from the one in A.
I have a few cases I wonder about. First, if you have no constructor:
class NoCons { int x; }
When I do new NoCons(), the default constructor gets called. What does it do exactly? Does it set x to 0, or does that happen elsewhere?
What if I have this situation:
class NoCons2 extends NoCons { int y; }
What happens when I call new NoCons2()? Does NoCons's default constructor get called, and then NoCons2's constructor? Do they each set the respective x and y fields to 0?
What about this version:
class Cons2 extends NoCons { int y; public Cons2() {} }
Now I have a constructor, but it doesn't call the super class's constructor. How does x ever get initialized? What if I had this situation:
class Cons { int x; public Cons() {} }
class NoCons2 extends Cons { int y; }
Will the Cons constructor be called?
I could just try all these examples, but I can't tell when a default constructor is run. What's a general way to think about this so that I'll know what happens in future situations?
When a Java class has no constructor explicitly defined a public no-args default constructor is added so:
class Cons { int x; }
is equivalent to:
class Cons { int x; public Cons() {} }
A subclass's constructor that doesn't explicitly define which of its parent's constructor it calls will automatically call the default constructor in the parent class before it does anything else. So assuming:
class A { public A() { System.out.println("A"); } }
then this:
class B extends A { public B() { System.out.println("B"); } }
is exactly equivalent to:
class B extends A { public B() { super(); System.out.println("B"); } }
and the output in both cases will be:
A
B
So when you do:
new NoCons2();
The order is:
NoCons's default constructor called, although this is technically the first part of (2); and then
NoCons2's default constructor called.
You want to refer to the Java Language Specification section 12.5 Creation of New Class Instances to get the official rules of object creation. The relevant section is:
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5. (In some early implementations, the compiler incorrectly omitted the code to initialize a field if the field initializer expression was a constant expression whose value was equal to the default initialization value for its type.)
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
So in your examples, when no constructor is supplied in your class definition, the default one is inserted for you. When you write
new NoCons2();
First the super constructor is called (a call to super() is inserted for you because you don't make the call explicitly).
Instance variables for the class being constructed are initialized.
The rest of the constructor body is executed (nothing in your case).
In your first example, x will be set during the construction of NoCons and y will be set during the construction of NoCons2.
So the exact sequence of events in that example will be something like:
NoCons2 constructor called.
Call to super(), goto 3
NoCons constructor called.
Call to super(), which is an implicit call to Object().
Whatever happens in Object constructor.
x is set to 0.
finish body of NoCons constructor, return control back to NoCons2 constructor.
y is set to 0.
finish body of NoCons2 constructor
NoCons2 object construction complete.
cletus answered the biggest of the questions. The answer to the other is that member variables in Java are initialized to 0, null or false (depending on the type).
Here is essentially what happens when "new" is called:
the memory is allocated (enough to hold all of the data members of the class, and all of the parent classes, and some housekeeping information)
the allocated memory is set to zero (which means 0, 0.0, false, null depending in the type)
the constructor is called for the class that is after "new" is called.
more things happen (coming after the next part)
If you do not provide a constructor the compiler does the following:
creates a no-argument constructor
the created constructor has the same access as the class (so public or package)
super() is called.
So when the constructor of the class after the "new" is called the very first thing it does is call "super()" which calls the parent constructor. This happens all the way up to java.lang.Object.
Before the body of the constructor is run the VM does the following:
the instance variables that are assigned values are given them
then the instance initializer block, if present is run.
The following code shows all of this:
public class Main
{
private Main()
{
}
public static void main(final String[] args)
{
final Foo fooA;
final Foo fooB;
fooA = new Foo(7);
System.out.println("---------------------");
fooB = new Foo(42);
}
}
class Bar
{
protected int valueA = getValue("valueA", 1);
protected int valueB;
static
{
System.out.println("static block for Bar happens only one time");
}
{
System.out.println("instance block for Bar happens one time for each new Bar");
System.out.println("valueA = " + valueA);
System.out.println("valueB = " + valueB);
}
Bar()
{
super(); // compiler adds this - you would not type it in
System.out.println("running Bar()");
System.out.println("valueA = " + valueA);
System.out.println("valueB = " + valueB);
valueB = getValue("valueB", 2);
}
protected static int getValue(final String name, final int val)
{
System.out.println("setting " + name + " to " + val);
return (val);
}
}
class Foo
extends Bar
{
protected int valueC = getValue("valueC", 1);
protected int valueD;
static
{
System.out.println("static block for Foo happens only one time");
}
{
System.out.println("instance block for Foo happens one time for each new Foo");
System.out.println("valueC = " + valueC);
System.out.println("valueD = " + valueD);
}
Foo(final int val)
{
super(); // compiler adds this - you would not type it in
System.out.println("running Foo(int)");
System.out.println("valueC = " + valueC);
System.out.println("valueD = " + valueD);
valueD = getValue("valueD", val);
}
}