Why this code print value of super class instead of sub class - java

class A{
int a = 10;
}
class B extends A{
int a= 20;
}
public class C {
public static void main(String [] args){
A a = new B();
System.out.println(a.a);
}
}
output : 10
How it print value from base class based on above code.

B already inherits a from A. Doing int a = 20; again hides the a inherited from A. This means that an expression of the form x.a will only evaluate to 20 if the compile time of x is B.
To get your expected behaviour, you can reset a in the constructor of B:
class B {
// no need to redeclare "a" here!
public B() { a = 20; }
}

When you make a variable of the same name in a subclass like you have done here, its called hiding. The resulting subclass will now actually have both properties.
Please refer below image,

Related

this keyword differs in Runtime and compile time

1.Can Some one illustrate how it works? Why it prints 1 instead of 2?
2.From the Oracle Official Java tutorial, the definition of this: Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this.
// Base Class
class A {
public int m = 1;
public void view(){
// Print variable m
System.out.println(this.m);
//print the current class name
System.out.println(this.getClass());
}
}
// Subclass extends Base Class
public class B extends A{
// Define another variable m
public int m = 2;
public static void main(String[] args) {
B b = new B();
b.view();
}
}
Below is the debug of the view(){}:
My Question is:
You can see the current object is B, when we usethis, it represents the B, m = 1 in base class A, m = 2 in derived class B, then use the this.m, it should print 2, isn't it?
Variables are not polymorphic in Java; they do not override one another.

initialization blocks in polymorphism

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.

when is the method of the object type instead of object is called in Java especially in static binding?

my question may not been very clear. looking through this example, I can explain further.
As I reading the answers posted for this Static vs Dynamic Binding Logic , I got this question.
There are two version of code, both of which are exactly the same, except for change in parameter type for Class B p (double i)
version 1:
import java.lang.*;
public class X
{
public static void main(String [] args)
{
B c = new A();
c.p(10);
c.p("AAA");
((A)c).p(10);
}
}
class B {
public void p(String s)
{
System.out.println("B: my string is " + s);
}
public void p(int i)
{
System.out.println("B: twice my double is: " + i*2);
}
}
class A extends B{
public void p(int i)
{
System.out.println("A: my number is " + i);
}
}
Here the output is :
A:my number is 10
B: my string is AAA
A: my number is 10
version 2:
import java.lang.*;
public class X
{
public static void main(String [] args)
{
B c = new A();
c.p(10);
c.p("AAA");
((A)c).p(10);
}
}
class B {
public void p(String s)
{
System.out.println("B: my string is " + s);
}
public void p(double i)
{
System.out.println("B: twice my double is: " + i*2);
}
}
class A extends B{
public void p(int i)
{
System.out.println("A: my number is " + i);
}
}
Here the output is :
B:twice my double is 20.0
B: my string is AAA
A: my number is 10
my question is as follows:
why the p(int) from Class A is called in the first version while p(double) from Class B is called in the second version.
version 1:
methods of A
A -----> p(string), p(int)- this is overridden from Class B
method of B
B ------> p(string), p(int)
version 2:
methods of A
A -----> p(string), p(double), p(int) No more overriding
method of B
B ------> p(string), p(double)
when I declare B c;, I initialize the reference variable which is of type B
next I assign c to the new object, by c = new A();
hence this declaration B c = new A(); creates an instance of class A and assigns to the variable of type B. now whenever the methods calls are executed on c, the compiler first checks if the methods exists in B (since it is of B type), but the actual method that is called is of the object (which is an A instance).
why this behavior is not seen in the above example? or if my reasoning is wrong, kindly correct me.
Thanks
In the first version you override a method and in the second method you overload it.
In the first version you have p in both class A and class B. When you call c.p(...) the compiler uses the static type of c to create the call. On run time the code uses the class`s virtual table (read about it if you're not familiar) in order to find the correct polymorphic method.
In the second version the compiler does the cast from int to double for you on compile time and then on run-time it again uses the virtual table of A to find a method with signature p(double) (because it casted the int on compile-time for static-type compliance). The virtual table points to the method in B because A doesn't override it.
You can further read about it in the book "Effective Java" - Item 41, Page 191:
selection among overloaded methods is static, while selection among overridden methods is dynamic

Static vs Dynamic Binding Logic

I have the following code:
import java.lang.*;
public class Program
{
public static void main(String [] args)
{
B a = new A();
a.p(10);
a.p(10.0);
}
}
class B {
public void p(double i)
{
System.out.println(i*2);
}
}
class A extends B{
public void p(int i)
{
System.out.println(i);
}
}
When I execute this code using B a = new A() , I get 20.0 in both cases which makes sense because overloading is handles during compile time where the compiler looks at the declared type and calls a function appropriately. Since our declared type was class B, class B's method was called in both cases. Now if I do A a = new A(); , I should be getting 10 in both answers but I am not. I am getting 10 for a.p(10) and 20.0 for a.p(10.0). Based on the concept of static binding and whole notion of overloading being done by static binding which looks at the declared type as opposed to the actual type, why is the result coming out this way ? I would very much appreciate your help.
An int can be widened to a double, but not the other way around. This means that 10 can call B.p(double) or A.p(int) but 10.0 is a double and will not be implicitly converted to an int i.e. only B.p(double) will be called.
Its because your method p is not an overridden method, it is just inhereted in your sub-class when you use
Super sup = new Sub();
sup.p(int);
sup.p(double);
In this case as your Super class has a method which takes double as a parameter and aa an int can fit into a double your Super-class's method is invoked the one which accepts double.
Sub sup = new Sub();
sup.p(int);
sup.p(double);
In this case however, as your subclass doesn't have a method which takes a double, for sup.p(double) call it uses the inherited method from super class if you pass double as an argument.
In your case, your are doing overloading which will get binded at compile time(static binding.).And static binding happens with type of reference rather than the type of object the reference is pointing.
In your first case you are using a reference variable of B and assigning an object of A to it.Since your reference is B, the method p(double) from B will get binded statically even if you use an int(since int can be widened to double).
In the second case you are using reference as A itself.In this case, you have two p() methods available.One is p(double) from B and other p(int) from A.So p(10) will call p(int) and p(10.0) will call p(double)
Try this:
class B {
public void p(String i)
{
System.out.println("parent:"+i);
}
}
class A extends B{
public void p(int i)
{
System.out.println(i);
}
}
public class Test1 {
public static void main(String args[]) {
A a = new A(); //arg
a.p(10);
a.p("sample");
}
}
If you change the line marked arg to B a = new A(), you will see compiler trying to call parent p in both the cases.
When you write A a = new A() you create a new object of type A, which will have 2 methods. A.p(int) and B.p(double), and when you call A.p(10.0), it will call B.p(double) due to lack of conversion.
This counter-example might help:
import java.lang.*;
public class X
{
public static void main(String [] args)
{
B c = new A();
c.p(10);
c.p(10.0);
c.p("AAA");
((A)c).p(10);
}
}
class B {
public void p(String s)
{
System.out.println("B: my string is " + s);
}
public void p(double i)
{
System.out.println("B: twice my double is: " + i*2);
}
}
class A extends B{
public void p(int i)
{
System.out.println("A: my number is " + i);
}
}
Output:
C:\temp>java X
B: twice my double is: 20.0
B: twice my double is: 20.0
B: my string is AAA
A: my number is 10
The issue is:
1) You're declaring the type as "B" (not "A")
2) B.p(10) can accept an int as a floating point argument
3) Consequently, that's what you're getting
It's really an issue of what argument types can be implicitly converted, than what methods are overloaded or overridden.
When the object has declared type B, the double version is invoked because it's compatible with an int argument, since in Java int is a subtype of double.
When the object is declared as a A, it has the method p() overloaded with two versions:
p(int arg);
p(double arg);
So, when you pass an int, the first version is picked because it's more accurate, and when you pass double the second one, because it's the most specific signature.
For reference, see the relevant JLS at §15.12.2 and this post by Gilad Bracha. BTW, don't try to figure out how the language should behave based on what you think is the most logical way, because every programming language is an engineering effort, and this means that there's a price you pay for whatever you take. The primary source of information for Java are the JLS, and if you read it carefully, you'll (surprisingly?) discover that there are even cases where the line in the source code is ambiguous and cannot be compiled.
To make the effect of widening of int to double more vivid I have created another example which is worth looking. Here, instead of double I have created a class called Parent and instead of int a Child class is created.
Thus,
double ~ Parent int~Child
Obviously child object can be widened to Parent reference.
package test;
public class OOPs {
public static void main(String[] args) {
Child ch = new Child(); // like int 10
Parent pa = new Parent();// like double 10.0
B a = new A(); // case 2 : A a = new A();
a.p(ch);// 10
a.p(pa);// 10.0
}
}
class B {
public void p(Parent i) {
System.out.println("print like 20");
System.out.println(i.getClass().getName());
}
}
class A extends B {
public void p(Child i) {
System.out.println("print like 10");
System.out.println(i.getClass().getName());
}
}
class Parent {
String name;
Parent() {
name = "Parent";
}
public String getName() {
return name;
}
}
class Child extends Parent {
String name;
Child() {
name = "Child";
}
public String getName() {
return name;
}
}
Case 1 - Output (B a = new A();)
print like 20
test.Child
print like 20
test.Parent
Case 2 - Output (A a = new A();)
print like 10
test.Child
print like 20
test.Parent

overriding a variable in java

public class Foo {
public int a = 3;
public void addFive(){
a += 5; System.out.print("f ");
}
}
public class Bar extends Foo {
public int a = 8;
public void addFive(){
this.a += 5;
System.out.print("b " );
}
}
public class Test {
public static void main(String args[]){
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
}
}
I am getting output b 3 .why it is not giving b13 as output.Can anyone please explain.
Assuming class Foo is declared as below
class Foo
{
public int a = 3;
public void addFive()
{
a += 5;
System.out.print("f ");
}
}
Variables have no concept of overriding. They are just masked.
It is printing 3 because, when you use a superclass reference to access a variable, it accesses the variable declared in superclass only. Remember that superclass doesn't know anything about subclass.
class Foo {
public void addFive() {
a += 5; System.out.print("f ");
}
}
you don't have 'a' variable defined, so this example doesn't even compile.
correct code:
class Foo {
public int a;
public void addFive() {
a += 5; System.out.print("f ");
}
}
and see link https://stackoverflow.com/a/2464254/1025312
I assume that you meant to declare an integer field a in class Foo.
The answer to your question has to do with concepts of 'overriding' and 'hiding', as others have pointed out. Another way to explain it is that for member variables, there is no such thing as 'dynamic dispatch'. What that means is that, if you access a member of a certain object, the system checks at run time which member you mean, by looking at the class hierarchy.
So, when calling the method f.addFive, at run time, the system will see that your object is actually a Bar and not a Foo, and so take the addFive function that you defined in the Bar class.
That does not happen for member variables: you access f.a in your print statement, and at compile time it is decided that right there you want to access the field a declared in class Foo there -- and so, that is what will happen at run time.
Now, the reason that there is no dynamic dispatch for member variable access is performance: it would be very expensive to go through the whole 'see what object this really is' logic every time you just want to add some value to a member variable.
Declaring public int a = 8 in Foo class instead of Bar class it should work... printing B 3.
But I suppose you are talking about a question included in the Java certification exam, so you have to correct the code of the Foo class adding public int a = 3.
You cannot override a variable in Java, but declaring in as public (or protected) in the super-class you can use it also in all inherited classes.
In this case the right output is B 13 because in the test class you are using a Bar object as a Foo object, so the value of a is 3 and not 8.

Categories