Hello everyone,
I am very surprise to see the following program's output:
class A{
int f() {return 0;}
int g() {return 3;}
}
class B extends A{
int f() {return 1;}
int g() {return f();}
}
class C extends B {
int f() {return 2;}
}
public class Test {
public static void main(String args[]){
A ref1 = new C();
B ref2 = (B)ref1;
System.out.println(ref2.g());
}
}
Please help me to explain the code.
You are creating an instance of C and assigning it to the ref1 with type A. Further you are declaring a variable ref2 of type B which get assigned the value of ref1. The value of ref1 is still an instance of C even if you are viewing it by the type of class A.
Calling ref2.g() executes the method g() on the instance of the variable ref2. This is still the one and only created instance of C. Looking on it by the type of class B doesn't change the implementation of the instance the variable ref2 is referring to.
Let us extend class C by a method int h() { return 5; }. Using ref2 you cannot call method h() because the type of the variable is B. But h() is still present on the instance ref2 is referring to. If you extend the main method by
C ref3 = (C) ref2;
System.out.println(ref3.h());
this will output 5. But assigning the value of ref2 to ref3 and calling on it h() implies that the value of ref2 and ref3 (and ref1) is the same.
System.out.println(ref2 == ref3);
This outputs true. So both variables refer to the same object, the instance of C.
I will try to explain by steps:
Reference ref1 points to the instance of the class C.
Reference ref2 points to the same instance of the class C. No matter that it was done with explicit typecast, the instance in the heap still has the type C. Again:
ref2 has the type B;
object instance that ref2 is pointed to has the type C.
When we call to ref2.g(), JVM actually try to find method g() in class C (because object instance in heap has the type C, as was stated above). Because there is no method g() in class C, JVM moves to the parent class B, finds method g() in it, and calls it.
Call to method g() in class B leads to method f(). JVM again try to find that method initially in class C, finds it and return value 2.
This code represents overriding. And in overriding at runtime the jvm decides that which method to call (also called late binding).
Now come to code, the class C has the overridden method f() and in the code you have type-casted the reference of class A (ref1) to class B and called to g() method, so at runtime the jvm will call g() method of class B and ref2 is a reference of class B, which is pointing to class C object, so at runtime the f() method of class C has binded and it will call f() method of class C.
Related
class A{
int foo=10;
}
class B extends A{
int foo=10;
}
class Test{
public static void main(String [] args){
A a=new B();
System.out.println(a.foo);
//System.out.println(a.getClass());
}
}
In this case 10 is output. If I am not wrong, then this is because the a variable is of type A and variable assignment is static binding, and static binding is done at compile time by looking at the type of the variable. Since here a is of type A, then A's int foo is called. However when I call
System.out.println(a.getClass());
then this gives class B, that is a is of type B. I am confused about this. Kindly explain to me a is of which type and how A's int foo is printed.
But by looking at this code
class A{}
class B extends A{}
class Test{
public static void main(String [] args){
B b=new B();
A a=b;
B b1=(B)a; // compiles and run fine (a is of type B)
}
}
How is this possible? What's happening here? First b is of type B then in the second line a becomes of type A, as A a=.. is written but a.getClass() gives that it is of type B. How? If a is of type B then why is it calling A's int foo in the first example? Kindly explain both examples.
Also, does type casting change references or do any other stuff?
An important thing to realise is that Java only has primitive and reference variable types. This means when you write
A a =
The a is just a reference to an object (or null) not an object.
When you do
A a = new B();
there is no cast here, no work is done, no object is harmed or changed.
When you call an instance method on a class, it calls the method for the class of the object.
Object o = new B();
assert o.getClass() == B.class;
a longer example
B b = new B();
A a = b;
assert a == b; // always true as they point to the same object.
assert b.getClass() == B.class;
// so it makes sense that since a == b
assert a.getClass() == B.class;
type casting change references or do any other stuff?
It changes the type of the reference and it doesn't do other stuff like change the type of the object.
methods follow inheritance, however fields follow the type of the reference as a field cannot be overridden, it can only be hidden.
B b=new B(); A x=b; B b1=(B)x; // compiles and run fine (x is of type b) in this line when x is of which type
correct and you wouldn't be able to (B)x unless x was a reference to a B The variables x is an A which means it must point to an A object or a sub-class of a A e.g. B you can write
B b = new B();
A x = b;
assert x == b; // they still point to the same object.
B b1 = (B) x;
assert b1 == b; // same object
assert x == b1; // same object.
No new objects are created, nor is the object changed.
Quite simple why it does print the foo of A, because a is defined as A. Since there is no overriding for variables you are simply accesing the variables which are accesible for the type the variable is declared, which is A in this case.
public static void main(String[] args) {
A a = new A();
System.out.println(a.foo); // prints the foo of A, since a is of the type A
A b = new B();
System.out.println(b.foo); // prints the foo of A, since b is of the type A
B c = new B();
System.out.println(c.foo); // prints the foo of B, since c is of the type B
}
In the end it´s called shadowing what you are doing there. Your class B has a variable with the same name as A. Since they are not overridable you are able to hide foo of A, if your variable is of the type B, where you are accessing foo of B
Your question is related to Javas polymorphic behavior and dynamic (late) vs. static (early) binding.
The access to all the member variables in Java follows static binding. That means you have no polymorphism in this case. Instance Methods are dynamically bound. The instance method used for an invocation will be determined by the class of the object, not by the reference type. For example:
public class Main {
static class A{
String foo="A";
public String getFoo() {
return foo;
}
}
static class B extends A{
String foo="B";
#Override
public String getFoo() {
return foo;
}
}
public static void main(String[] args) throws Exception {
A a=new B();
System.out.println(a.foo); // prints A
System.out.println(a.getFoo()); // prints B
System.out.println(a.getClass()); // prints Main$B
}
}
Late binding
Early Binding
Polymorphism
Suppose I have 2 classes ........A Class is base class and class B is derived class and if i create a reference such as : A a=new B(); does it mean that reference a points to object of B Class ? If yes than how am i able to call overridden methods of A in B and not other methods of B ? thank you in advance
class A {
m1() {
}
}
class B extends A {
m1() {
}
m2() {
}
}
A a=new B();
a.m1(); //it will call overridden m1() in B
a.m2(); //it doesnt work if reference "a" points to object of B than why doesnt it call m2 method ?
Animal a=new Dog(); // Animal is parent - class, Dog is a child
means, you have an animal reference pointing to a Dog Object. So, only the methods which are declared in the parent class (Animal) can be called using a parent- class reference.
In your case, m2() is not defined in Class A, it is only defined in class B so, using a reference of A, you can't call m2()
If yes than how am i able to call overridden methods of A in B and not other methods of B
Because the reference is of type A. The compiler can only enforce calling the methods from this type.
I don't understand how exactly it works.
We have two class A and B. Class B extends A.
Class A have x attribute, and test method which modify this attribute.
Class B have x attribute, and test method which modify this attribute.
public class A {
int x;
public void test() {
this.x = 1;
System.out.println("A" + getX());
}
int getX() {return x;}
}
public class B extends A {
int x;
public void test() {
this.x = 2;
System.out.println("B" + getX());
}
int getX() {return x;}
}
public class Main {
public static void main(String[] args) {
A a = new A();
a.test();
System.out.println(a.getX());
System.out.println("point 1");
a = new B();
a.test();
System.out.println(a.x);
}
}
Output:
A1
1
point 1
B2
0
My prediction about last line of output was 2, but is 0. Why is 0?
Let's understand these lines of code:
a = new B();
a.test();
System.out.println(a.x);
You create a new object of B. It will re-initialize the variable - A.x = 0 and B.x = 0.
Then you invoke a.test(), which will call the overridden method test() in class B, which will set B.x to 2 using this.x = 2;. Note at this point, A.x is still 0.
Then you access a.x, which will access the field x in class A. The fields are not polymorphic. You don't override fields, but you hide them. The variable x in B hides the variable x in A.
If both A and B have a member named x, the one in B will block access to the one inherited from A. Remove the int x; declaration from B, or explicitly use super.x, if you want to reference the one in the parent class.
Starting from begin.
When you write
A a;
You say to JVM please reserve me in memory an address for something that fits A.
after when you do
a = new A();
You say to JVM, create a new object of class A and save the address to it under a
when you do this;
a.test();
You say to JVM, go to memory address a and from object there invoke method test().
Next thing what you do is this:
a = new B();
You say to JVM, create a new object of class B and save the address to it under a. No error here as B fits A as is a child class.
(You loose the connection with object of class A ass you changed it to B).
next operation is
a.test();
you also know this, but this time under address a is instance of class B. This time JVM search for the method in class B, if not fond then will search in class A.
I think you should start over with the Inheritance/Polymorphism concepts first.
But to make it clear: You have an object "a" which is declared as with type "A". Now, when you call the method test (which is overriden inside B in this case), the JVM calls the actual objects method. So, before "point 1" a.test calls A's test method, after "point1" it calls B's test method.
The problem is that this feature (called polymorphism) works only on methods. Whilst when you call an instance variable (as a.x) , the JVM calls the declared object variable. In this case is A. If you make a cast first, you'll get the right value: ((B)a).x
Note, the difference between actual and declared object is based on the type after the "new" operator (like new B()) and that in the object declaration
class A{
int a=10;
public void show(){
System.out.println("Show A: "+a);
}
}
class B extends A{
public int b=20;
public void show(){
System.out.println("Show B: "+b);
}
}
public class DynamicMethodDispatch {
public static void main(String[] args) {
A aObj = new A();
aObj.show(); //output - 10
B bObj = new B();
bObj.show(); //output - 20
aObj = bObj; //assigning the B obj to A..
aObj.show(); //output - 20
aObj = new B();
aObj.show(); //output - 20
System.out.println(bObj.b); //output - 20
//System.out.println(aObj.b); //It is giving error
}
}
In the above program i'm getting Error wen i try invoking aObj.b.
1.why i'm not able to acess that variable through the aObj though it is refering to class B??
2. why i'm able to acess the method show()?
You have to distinguish between the static type of aObj and the runtime type of aObj.
Code such as
A aObj = new B();
results in an aObj variable with static type A and runtime type B.
The compiler will only bother too look at the static type when deciding what to allow or not.
To your questions:
1.why i'm not able to acess that variable through the aObj though it is refering to class B??
Because there is (in general) no way for the compiler to know that aObj will refer to a B object at runtime, only that it will refer to some form of A object. Since .b is not available on all A objects, so the compiler will think "better safe than sorry" and disallow it.
2.why i'm able to acess the method show()?
Because this method is available in all A objects (if it's not declared in the subclass, it is still inherited from A).
aObj is a local variable of type A. A has no member called b, that's only in your subclass B. If you want to use b, you need to declare a variable of type B, but of course you can only assign it instances of B (or subclasses if there are any).
A declares a method show(), but you override the implementation in your subclass B.
This behavior is known as virtual method invocation, and it is an important aspect of polymorphism in Java. You should have a look at this tutorial.
class A{ // class A has variable a and method show();
int a=10;
public void show(){
System.out.println("Show A: "+a);
}
}
class B extends A{ //class B inherits variables and methods of A.
// so class B has variable a, b and show(). Also, show is overridden by class B.
public int b=20;
public void show(){
System.out.println("Show B: "+b);
}
}
since A doesn't have variable b inside it, even when u are passing B to A, you still have A object which does not have variable b inside it. So, trying to access b will give you compile time error.
in case of show(), A and B both have this method, so what you are doing here is actually overriding it at runtime. This is nothing but Polymorphism. So since A already has method show(), and it is overridden later by B,
A a = new B();
a.show();
this will run the show() method of B at runtime.
Methods and fields have different polymorphic behaviour.
The method that will be called is the method of the run time type of the instance
aObj=new B(); //new B()
The field that will be called is the field of the type of reference that you declared
A aObj = new A(); // A aObj
The following would work even is there was no show() method in A.
aObj = new B();
aObj.show(); //calls B's show()
I ran into this example about inheritances on the web, and I am not easy regarding its results. I'm missing something critical.
public class A {
int i = 5;
public A() {
foo();
}
private void foo() {
System.out.println(i);
}}
public class B extends A {
int i = 6;}
public class C extends B {
int i = 7;
public void foo() {
System.out.println("C's foo");
System.out.println(super.i);
}}
I'm trying to figure out what's happening by the following command: C c = new C();
System.out.println(C.i);
I know that when we create a new instance of C we approach A's and B's constructures, So We reach to A() - (question 1) Does i (of A) being initialize on the way?
Now we need to call to foo()- (question 2)- Does C's foo() consider as an override of A's foo()? and what if B had a foo() of itself? then it was consider as a override and C's foo() was operated?
As far as I know, there is no override when it relates to local variables. How come that System.out.println(c.i) is 7 and not 5? shouldn't it b the i of the highest-father?
EDIT: My question is not about which foo and i will be used when I use c, is about what happens during these two specific commands, cause obviously A's foo was used and not C's.
Thank you very much.
The three i variables here are completely independent. Which one is used by any statement is determined at compile-time - there's no polymorphism involved. So A.foo() will always print out the value of the variable declared in A.
Note that these aren't local variables by the way - they're instance variables.
When you print out c.i that uses the variable declared in C because the compile-time type of c is C. You can see this if you write:
C c = new C();
A a = c;
B b = c;
System.out.println(a.i); // 5 - variable declared in A
System.out.println(b.i); // 6 - variable declared in B
System.out.println(c.i); // 7 - variable declared in C
Note that in a well-written program this sort of thing almost never causes a problem, as variables should be private.
No, you always use the the class member closest to the class you've instantiated. So, C c = new C(); will use i=7 and C's foo only. Class B's i is overridden by class C's i, just as A's i has been overridden by B's i.
There's no chaining going on, just overriding.
A, B, and C each have an instance variable called "i". If you have a C object and execute foo() you will print C's value for "i".
If you had put foo() in B rather than C, oddly you'd still get C's value for "i" if you have a C object, since the "outermost" version of "i" will be used.
About method overriding and visibility:
A.foo() is private. It means it's not visible to its subclasses. If you want B or C to override A.foo(), A.foo() needs to be protected or public. So in your code, B.foo() doesn't exist, because B doesn't know about A.foo().