public class Base {
public Base() {
x = 0;
bar();
}
public Base(int x) {
this.x = x;
foo();
}
public void foo() {
System.out.println("Base.foo : " + x);
}
private void bar() {
System.out.println("Base.bar:" + x.toString());
}
protected Integer x;
}
public class Derived extends Base {
public Derived() {
bar();
}
public Derived(int x, int y) {
super(x);
this.y = y;
}
public void foo() {
System.out.println("Derived.foo : " + x + ", " + y);
}
public void bar() {
System.out.println("Derived.bar:" + x.toString() + ", " + y.toString());
}
private Integer y;
public static void main(String[] args) {
Base b = new Derived(10, 20);
}
}
Why does it print "Derived.foo:" 10, nulll and not 20 instead of the null?
y is a private variable of Derived, and it was initialized with 20. it's in its scope.. so why is it null?
Because the super constructor is first called (super(x)). This super constructor calls the method foo. Then the Derived constructor initializes y to 20 (this.y = y). So when foo is called, y is not initialized yet.
It's a bad practice to call overridable methods in constructors, because, as you just noticed, it can call overridden methods on partially constructed objects.
The println comes from method foo which is called from Base's constructor, which is called from Derived's constructor (via super) before you initialize y. So the null value is expected.
It does that because the superclass (Base) constructor calls Derived.foo() before the y member variable has been set.
So here is the basic order of operations:
main(...)
Derived(10,20) (start constructor)
Base(10) (start constructor)
this.x = x
foo() (calls Derived.foo() which prints the message you see)
Then after that
this.y = y
If you follow the calls from the constructor it makes it clearer:
Calls the Derived(int x, int y) constructor
Calls the super constructor Base(int x)
Sets the x variable
Calls the overridden foo() method
Performs the println()
Then sets the y variable
As you can see, the y variable is getting set after you try to print out the value. That is why you are seeing the uninitialized value of null.
Calling overridable methods from a constructor is a common mistake, as it can allow uninitialized variables to escape before the object is fully constructed.
When you get into the constructor of the super class y is not yet instantiated yet. So the call to foo() will have a null y.
It is printed by Derived.foo() triggered by Super-Constructor call before it is initialized with 20 afterwards. So while printing it is still null.
All the answers are indeed correct but next time you can maybe put a breakpoint in the function where you are printing something.
Then you can simply examine the call stack and folow the code by reading the parts that are being called.
This way you could have traced that y would not be initialized.
Good luck!
Roel
because y has not been initialised when foo() is called in the Base class constructor.
the chain goes
main -> Derived(x,y) -> Base(x) -> initialise x, foo(). However, because you're starting the call inside Derived, which overrides foo(), derived's foo() is actually executed by the interpreter.
Related
I couldn't understand the behavior of the below code.
My expectation was that it should print 100 in both println() methods. Why the result is different?
If I uncomment getX() method in inner class, then the output of println() methods are the same which is 100.
I couldn't figure out the reasoning of different behavior. Please help me to understand.
public class Foo {
public static void main(String[] args) {
MyOuter outerObj = new MyOuter();
MyOuter.MyInner innerObj = outerObj.new MyInner();
innerObj.setX();
System.out.println("x: " + innerObj.getX()); //x: 3
System.out.println("x: " + outerObj.getX()); //x: 100
}
}
class MyOuter {
private int x = 3;
public int getX() { return x; }
class MyInner extends MyOuter {
public void setX(){ x = 100; }
// public int getX() { return x; }
}
}
From MyInner's perspective, there are two private int x fields in play here:
One field super.x that is inherited from MyOuter, but inaccessible because it is declared as private, and MyInner as an inheriting object cannot access this field.
One field MyOuter.this.x from the sorrounding MyOuter-instance (since MyInner is a (non-static) inner class, it is always bound to an instance of the surrounding MyOuter), that is accessible.
The method setX() in MyInner cannot access the inherited field super.x, thus it accesses the field MyOuter.this.x and sets its values to 100. A consecutive call on the surrounding MyOuter's getX() will return 100.
The call innerObj.getX() (which is inherited from MyOuter and can access super.x) returns the value of the inherited field super.x (still having its initial value of 3).
If we remove the extends MyOuter from and include the getX()-method in MyInner, the code behaves as expected.
The fact that MyInner cannot access the inherited field private x is confusing at first, but the behaviour is actually in line with the behaviour of the keyword protected in the context of static mehthods in inheriting classes as discussed in this post by Hariharan
Code:
public class X
{
public void methodA() //Base class method
{
System.out.println ("hello, I'm methodA of class X");
}
}
public class Y extends X
{
public void methodA() //Derived Class method
{
System.out.println ("hello, I'm methodA of class Y");
}
}
public class Z
{
public static void main (String args []) {
X obj1 = new X(); // Reference and object X
X obj2 = new Y(); // X reference but Y object
obj1.methodA();
obj2.methodA();
}
}
Output:
hello, I'm methodA of class X
hello, I'm methodA of class Y
The method from the object type is getting called instead of the reference type. Isn't the out put in both lines supposed to be this?
hello, I'm methodA of class X
hello, I'm methodA of class X
The compiler chooses a method signature that best matches the method call (out of all the overloaded methods having the same name which are available for the compile time type of the variable for which the method is called).
However, the method that actually gets executed is only determined at runtime, based on the run time type of the instance refered by the variable for which the method is called. That's what method overriding means.'
You may be confusing method overloading (done at compile time) with method overriding (done at run time).
It is obvious. when you declare methodA() again in subclass. The methodA() of super class is overridden. So now whenever you call methodA(), the methodA() of subclass will be called.
X obj1 = new Y();
Y obj2 = new Y();
obj1.methodA();
((X)obj2).methodA();
both will call the overriden method.
In java there is no way to call the method which is overridden. Only the thing you can do to call superclass's method while overriding a function is this :
public void methodA() { //Derived Class method
super.methodA();
// add other stuff if you want here
}
Java uses 'early binding', i.e. associating a name to a method during compilation, and 'dynamic dispatch', selecting the method implementation most closely associated with the object's type at runtime.
Java uses the reference type when binding because the object's type may not be known during compilation.
X obj1 = new X(); // obj1 is bound to X and of type X
if (i == 0) {
obj1 = new Y(); // obj1 is still bound to X, but now of type Y
}
obj1.methodA();
// Due to early binding, a compiler error occurs if X doesn't contain methodA
// Due to dynamic dispatch, if it exists, the methodA of obj1's type will be used. Otherwise the closest superclass's methodA will be used.
In the following example, I don't understand why Base b1 = new Derived();
System.out.println(b1); prints out x=10, z=20. My understanding is that since b1 has a static type of Base, it don't have access to the fields in Derived, so z shouldn't haven been printed out. Can someone please help to explain? Many thanks!
class Base {
int x;
public Base1() { x = 10; }
public Base1(int x) { this.x =x; }
public String toString() {
return "x=" + x ;
}
}
class Derived1 extends Base1 {
int z = x * 2;
public Derived1() {}
public Derived1(int x, int z) {
super(x);
this.z = this.z + z;
}
public String toString() {
return "x=" + x + ", z=" + z;
}
}
The object is a Derived, not a Base. Your interface to the object from b1 is Base. Base has toString, so you can access toString. The implementation you access is the one the object has, which is provided by Derived, which uses z. The implementation of Derived#toString can access z because its reference to the object is via a Derived reference (this), not a Base reference.
As Oli points out in a comment, this is fundamental to polymorphism — having the behavior of the object depend on the object rather than the interface to the object.
If the internals of the object were dictated by the interface we had to it, we'd be in a fair bit of trouble trying to implement interfaces! :-)
Straight from http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
A subclass inherits all of the public and protected members of its
parent, no matter what package the subclass is in. If the subclass is
in the same package as its parent, it also inherits the
package-private members of the parent. You can use the inherited
members as is, replace them, hide them, or supplement them with new
members
In your code you call the default constructor to create a new Derived1 object : Base b1 = new Derived();and this in turn calls the default constructor of the parent class where there you happen to set x = 10. After that, you go to this line int z = x * 2;
I have following classes:
public abstract class AClass {
public AClass() {
aMethod();
}
abstract protected void aMethod();
}
public class SubClass extends AClass {
private int x = 5;
private static final int y = 6;
#Override
protected void aMethod() {
System.out.println("x: " + x + " | y: " + y);
}
}
public class Main {
public static void main(String[] args) {
new SubClass();
}
}
Running Main prints the following: x: 0 | y: 6
Why does 0 get printed for x?
The reason of the misbehaviour is a wrong initialization sequence:
new SubClass() executes AClass constructor
AClass constructor calls aMethod()
aMethod() shows x (which is 0 so far) and y which is 6 because of being static)
SubClass initialize its non-static fields, so x becomes 5.
To avoid surprizes, never call virtual methods (esp. overriden) in constructors
The static field is initialized as soon as the class is initialized (after loading). Now when you call
new SubClass() the following things happen.
Constructor of SubClass is called as the first statement of SubClass (implicitly)
Constructor of SuperClass is called. --> you are checking value of x here
Once SuperClass constructor's execution completes, then instance level fields of SubClass are initialized. So x will be initialized here.
Initialization order. aMethod() is called before the line private int x = 5
Playing round with code examples like this is a great way to learn the order in which things are executed. Try adding a static and non-static initialization block too.
The result is because the super class constructor is called before the members are initialized.
In your case the following sequence is executed:
Call to constructor SubClass
immediate call to constructor AClass
call of method aMethod()
initializing of members of SubClass
This is also the reason why you should not call any overrideable methods from a constructor as the called method may access the state of an object that is not fully initialized.
private static final int y = 6;
Value of y is 6 when the constructor calls aMethod(), because it is static and is initialized while class loading.
private int x = 5;
While this initialization is appended at the end of your constructor body. It means while aMethod is being executed, the variable x has still default value i.e 0.
Default constructor of SubClass would look like
SubClass() {
super();
//All instance initialization are performed here.
}
Because when you created an instance of the Subclass it invokes the constructor of its super class AClass, and at this point, x was not yet set that's why it gets the default value of 0.
So, I have these 3 classes in Java.
When I run the program I get:
20,
15,
10,
My question is, why do I get this instead of:
15,
20 (doesn't public int getX(); in class B get us to 15+5=20?),
10
for example?
Can you please explain to me , step by step, what really happens in this program because I am very confused with the output(and the sequence).
public class A {
private int x = 15;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public void printX() {
System.out.println(this.getX());
}
}
Child:
public class B extends A {
private int x = 5;
#Override
public int getX() {
return super.getX() + x;
}
#Override
public void setX(int x) {
super.setX(x);
super.printX();
}
#Override
public void printX() {
System.out.println(super.getX());
}
}
and
public class C {
public static void main(String[] args) {
A a = new B();
System.out.println(a.getX());
a.setX(10);
a.printX();
}
}
This is happening because you instantiate a as a B object - A a = new B(). It doesn't matter that the explicit type of a is A; it's more generic (abstract) than its real type B (because B inherits from A), therefore polymorphism calls B methods (more specific) in first order. The same applies to fields.
After calling a.getX() class B references to A's getX(), which returns its 15 (superclass method has no reference to the object it was called from in this case), then 5 (B's x) is added, resulting in 20.
The subsequent calls behave in a similar manner.
I have given a basic example similar to your problem go through it you will get your answer. This is the concept of runtime polymorphism
Inheritance creates typecompatibility. It allows a super class reference to refer to the object of sub class. (Reverse is not true).
A super class reference, that refers to object of sub class, can only be used to access the inherited and overrridden methods of sub class. The members newly defined in sub class are not accessible using reference of super class.
class A
{
void f1()//this holds address of object of B
{
System.out.println("A f1");
}
void f2()
{
System.out.println("A f2");
}
}//A
class B extends A
{
void f3()//new method
{
System.out.println("B f3");
}
void f2()//this holds address of object of B
{
System.out.println("B f2 starts");
f3(); //this.f3()
System.out.println("B f2 ends ");
}
}//B
class TypeCmptbl
{
public static void main(String args[])
{
A ref; //reference of A
ref = new B();//Object of B
//ref.inherited() allowed
ref.f1();
//ref.overridden() allowed
ref.f2();
//ref.newMembersOfChild() not allowed
//ref.f3();
}//main
}
Consider the statement
ref.f2();
Here ref is a reference of class A and it has address of object of class B f2() is a overridden method.
When compiler detects such a statement then it doesn't bind the function call with any definition. It only validates the call.
Binding of such calls is left for the runtime environment. At program runtime system identifies the datatype of the object and binds the function call with the function definition provided by the class of object. This type of binding between the function call and function definition is called as "runtime polymorphism" .
Your question is related to the runtime polymorphism in java note that methods are bind at runtime, and the variables are bind at Compile time
In your example
public class C {
public static void main(String[] args) {
A a=new B();
System.out.println(a.getX());
a.setX(10);
a.printX();
}
}
// reference is of A but the object is of B, so at runtime JVM see that memory is of B so the B's method is called, this is runtime Polymorphism
when the below statement is called , the getX() of class B is invoked.
System.out.println(a.getX());
#Override
public int getX() {
return super.getX() + x; // this will add 15 from class A + 5 in this method.
}
the above statement displays 20
when the below statement is called,
a.setX(10);
#Override
public void setX(int x) {
super.setX(x); // observe this method, this prints 15
super.printX(); // this prints 10
}
//super.setX(x); it will call
public void setX(int x) {
this.x=x; // 10 <--- 15 so 15 is displayed
}
here this.x refers the value which is passed through a.setX(10).
A a = new B();
So the concrete type of a is B.
System.out.println(a.getX());
You're calling getX() on an object of type B. So the following method is called, because the concrete type of a is B, and B has overridden the getX() method defined by A:
public int getX() {
return super.getX() + x;
}
It adds B's x (whose value is 5), with the result of super.getX(). This method, in A, is defined as
public int getX() {
return x;
}
So it returns A's x, which is initialized to 15.
The result is thus 5 + 15 = 20.
The rest can be explained the same way. Remember that fields are not accessed in a polymorphic way. Only methods are. So, inside the code of A, when you see x, it always mean "the value of the field x in A". Inside the code of B, when you see x, it always mean "the value of the field x in B".
When you say:
A a = new B();
it means Object of A is instantiated with class B. So, in the memory, a space is reserved for your object 'a' which contains all the methods and properties of class B (not A).
So, when the first print statement is executed, it executes the getX() method of the class B and not the getX() method of class A.
For other methods called by your object 'a', the methods of the class B are called.
This is also known as dynamic binding, as JVM allocates the memory to the object 'a' at the run time and not compile time.
For more details on dynamic binding check these links:
http://www.tutorialspoint.com/java/java_overriding.htm
http://www.tutorialspoint.com/java/java_polymorphism.htm
I also suggest you to instal eclipse on your machine and run your code in the debug mode.
This is the best way you can study your code.