In this code I allocate one only object, but in some way I store 2 copies of x (one for the base class and one for the subclass). How is it possible if the object is only one? Where is the space found to store two x vars? Does it mean in reality two objects are createed?
class App {
class Base {
public int x;
public Base() {
x = 2;
}
int method() {
return x;
}
}
class Subclass extends Base {
public int x;
public Subclass() {
x = 3;
}
int method() {
return x;
}
}
public static void main(String[] args) {
new App().run();
}
public void run() {
Base b = new Subclass();
System.out.println(b.x);
System.out.println(b.method());
}
}
One x belongs to the superclass and the other to the subclass. The fact that they have the same name is of no importance and you can access both by qualifying your access expression with the class:
((Base)b).x
((Subclass)b).x
(note that the cast in the first line is not necessary; I've put it in for symmetry)
In java you can not overload variables.,Though they are with the same name,their classes are different.
According to this tutorial(in section "What You Can Do in a Subclass"), when you declare a field in the subclass with the same name as the one in the superclass, in this case x, the one in the superclass will be hidden, which means that there're actually two xs in the subclass, one for itself, the other for its superclass, only baring the same name x. You can reference to the one in the derived class using derivedObject.x and the one in the subclass using ((Base)derivedObject).x(or super.x if within the derived class)
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
interface A {
public static String name = "A";
}
interface B {
public static String name = "B";
}
class X implements A { }
class Y extends X implements B { }
public void test_getField() {
try {
assertEquals(B.class.getField("name"), Y.class.getField("name"));
} catch (NoSuchFieldException e) {
fail("Got exception");
}
}
Why does Y.class.getField("name") return B.name instead of A.name?
Is there any answer in the Java specification?
The direct superinterface will be searched before superclass, see the doc of getField:
The field to be reflected is determined by the algorithm that follows.
Let C be the class represented by this object:
If C declares a public field with the name specified, that is the
field to be reflected.
If no field was found in step 1 above, this
algorithm is applied recursively to each direct superinterface of C.
The direct superinterfaces are searched in the order they were
declared.
If no field was found in steps 1 and 2 above, and C has a
superclass S, then this algorithm is invoked recursively upon S. If C
has no superclass, then a NoSuchFieldException is thrown.
The key point here is that you're using reflection and getting unexpected behavior.
Although you already have the reflection algorithm, I will add a visual example.
First of all, using normal access you will get:
class Y extends X implements B {
public void test() {
System.out.println(name);
}
}
Error:(29, 36) java: reference to name is ambiguous both variable
name in com.test.A and variable name in com.test.B match
Now considering an example:
class Y extends X implements A, B {}
public class Main {
public static void main(String[] args) throws NoSuchFieldException {
Y y = new Y();
System.out.println("Y : " + y.getClass().getField("name"));
}
}
The output will be:
Y : public static final java.lang.String A.name
Changing signature to
class Y extends X implements A, B {}
Gives us output:
Y : public static final java.lang.String B.name
The direct superinterfaces are searched in the order they were
declared.
Further observation shows that actually we can get both names like:
class Y extends X implements A, B { }
public class Main {
public static void main(String[] args) throws IllegalAccessException {
Y y = new Y();
Field[] fields = Y.class.getFields();
for (Field field : fields) {
System.out.println(field.get(y));
}
}
}
Output:
A
B
And for both class Y extends X implements B { } and class Y extends X implements B, A { }:
B
A
The first name resolved in runtime comes from first implemented interface (direct superinterface) because it has higher precedence, then comes the value from the second interface, then the value from the superclass.
When you calling Y.class.getField("name") you're getting the first resolved name which comes from first direct superinterface - A.
This is an interesting question. Let's first simplify this a bit
static class Parent {
public int x = 1;
}
static class Child extends Parent {
public int x = 2;
}
public static void main(String[] args) {
Child c = new Child();
Parent p = c;
System.out.println(c.x);
System.out.println(p.x);
}
What do you think this will print?
It will be 2 1Instance variables are inherited, but they are not overridable. This is called hiding, Parent’s x is hidden by Child’s x. Instance variables are inherited, but they are not overridable. This is called hiding, Parent’s x is hidden by Child’s x.
The second line though… Where are we pulling x from? We do have a Parent reference, but it’s pointing to a Child instance, right? It’s like Child has two different variables with the same name; one it declares, one it inherits. Does it?
Arrays.stream(Child.class.getFields())
.map(Field::getName)
.forEachOrdered(System.out::println); // x x
It’s like Child has two fully qualified variables and depending on the reference you can access one or the other.
Now to your example (a bit simplified):
interface First {
int x = 3;
}
interface Second {
int x = 4;
}
static class Impl implements First, Second {}
What do you think this will print?
Arrays.stream(Impl.class.getFields())
.map(Field::getName)
.forEachOrdered(System.out::println);
As in the previous example, it will print x twice, the meaning of this is explained above.
Knowing this, let's go to your question (again, a bit simplified):
interface First {
int x = 1;
}
interface Second {
int x = 2;
}
class Impl implements First, Second {
}
Field left = First.class.getField("x");
// you might think that this will fail, since Impl has two variables x...
Field right = Impl.class.getField("x");
if (!left.equals(right)) {
throw new AssertionError("Aren't they equal?");
}
As the way this is written right now, this will NOT throw the AssertionError.
The idea here is that Field#equals uses 3 things for equality: type, name and declaringClass. The first two obviously match, so all we care about is the last one. And this is where the JLS comes at help which the other answer has already provided.
That is the reason btw, that if you change the order of interface declarations : class Impl implements Second, First that code will throw the AssertionError. Because now, x will be resolved from Second (in the order of the declaration... ), but we compare it with First.
What is the difference between these commands when I have a class A and a Class B where B extends A , and they have a common instance variable size and the commands below are called from a method printSize1 inside B?
class A {
protected int size;
}
class B extends A {
protected int size=7;
public void printSize1() {
System.out.println(((A)this).size)
System.out.println(super.size);
}
}
Also I have the same question with these two. I have a class A and a class B where B extends A, and they both have a method with the same name printSize and an instance variable size and the below commands are called from a method printSize2 inside class B.
class A {
protected int size;
public void printSize() {
System.out.println("Size=" + size);
}
}
class B extends A {
protected int size=7;
public void printSize2 {
((A) this).printSize();
super.printSize();
}
public void printSize() {
System.out.println ("MSize="+size);
}
}
i have a class A and a Class B where B extends A which they have a common instance variable size
No, they don't. They have separate instance variables called size. One is in the part of the object associated with A, and the other is in the part of the object associated with B. Let's call them A$size and B$size. For them to have a common instance variable, you'd remove the declaration of size from B so they're both using A$size.
Redeclaring an ancestor's non-private instance variable (field) is always a bad idea, because it leads to this sort of confusion.
Both of the below output 0 for your example code, because they're both accessing A$size, which you never assign a value to, so it has the default value 0:
System.out.println(((A)this).size); // 0
System.out.println(super.size); // 0
So the question is: Why are they both using A$size and not B$size? Because of the type of the reference we're using to look up size. In both cases, the type of the reference is A, because the type of (A)this is A (via cast) and the type of super in a method in B is also A. Since the type of the reference is A, it's A's size that gets used.
In this particular case there isn't much of a difference between the two, but there would be if you added another layer to the hierarchy:
class A {
protected int size = 1;
}
class B extends A {
protected int size = 2;
}
class C extends B {
protected int size = 3;
void printSize() {
System.out.println(((A)this).size); // 1
System.out.println(super.size); // 2
System.out.println(this.size); // 3
}
}
Moral of the story: Don't redeclare instance variables declared by an ancestor (unless the ancestor's version is private).
Note that this is different for variables than it is for methods. Instance methods are polymorphic. Instance variables are not. With methods, you get the method associated with the final type of the object (unless you use super or a qualified super, because those are special and bypass polymorphism).
This is what's coming into play in your second example in printSize2. Because methods are polymorphic, it doesn't matter that you've cast this to be type A in ((A)this).printSize(), you still get B's printSize. But super.printSize() is special because super is special and bypasses polymorphism, giving B access to A's printSize.
In the following code, I don't understand why when a1.k() is called, this.x in class C returns 100 instead of 1. My understanding is that this refers to the current object, but the static type of the current variable a1 is A. So shouldn't this.x returns 1, which is the variable for A type?
I mean a1.x should return 1, right? Many thanks!
class A {
public int x = 1;
public String k() { return "A" + this.x; }
}
class B extends A {
public int x = 10;
...
}
class C extends B {
public int x = 100;
public String k() { return "C" + this.x; }
}
class TestABC {
public static void main(String[] args) {
A a1 = new C();
C c1 = new C();
System.out.println(a1.k());
}
}
When you call a1.k() you dynamically dispatch to the k method that is defined by the actual object whose reference is in a1. In this case, it is a C not an A or a B, and hence the k method is the override defined in C.
The static type (of a1 for example) is used for static resolution; e.g. resolving static methods, overload signatures, and fields. But for instance method invocation, the ultimate selection of the method to be invoked is dynamic.
I know the k() in class C should be called, instead of the k() in class A. But why this.x returns 100? I thought the instance variable is bounded to the static type.
Well it is. But it is the static type that determines which x is used by this.x in the k() call is the static type of this in the C.k method body!
This feature is called Dynamic Polymorphism. The methods being called is not dependent of type of its declaration but by the type being assigned to it (definition).
For this the classes must inherit and also override the methods in the parent class.
Here C,B extends A and overrides the method k;
if you try to call some C specific methods or variable it will throw error. (Since A doesn't know about that)
A is holding reference to C (pointing to C)
a1.k is actually C constructed Object and its new C().k() where x is 100 in C.
class Base{
int x=10;
public int getx(){return x;}
}
class Sub extends Base{
int x=100;
public int getx(){return x;}
}
class Test
{
public static void main (String[] args)
{
Base b = new Base();
Sub s = new Sub();
System.out.println("sub: getx:"+s.getx()+" .x:"+s.x+" Class: "+s.getClass().getName());
System.out.println("base: getx:"+b.getx()+" .x:"+b.x+" Class: "+b.getClass().getName());
Base btoS = new Sub();
System.out.println("btos: getx"+btoS.getx()+" .x:"+btoS.x+" Class: "+btoS.getClass().getName());
}
}
Results in
sub: getx:100 .x:100 Class: Sub
base: getx:10 .x:10 Class: Base
btos: getx100 .x:10 Class: Sub
Since you declare a1 as new C(), a1 will be seen as an object instance of class C, which overrides the fields of its parent class B and A. So why you would do things like A a1 = new C(); (or you might see a lot of such implementation), there is a recommendation saying "programming to interface rather than the actual implementation.", and I think this explains better.
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.