Why is this method not selected depending on the type of runtime of the object?

Consider this:

class A { int x =5; } class B extends A{ int x =6; } public class CovariantTest { public A getObject() { return new A(); } /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here CovariantTest c1 = new SubCovariantTest(); System.out.println(c1.getObject().x); } } class SubCovariantTest extends CovariantTest { public B getObject(){ return new B(); } } 

As far as I know, the JVM selects a method based on the true type of its object. Here, the true type is SubCovariantTest, which is defined by the overriding getObject method.

The program prints 5 instead of 6. Why?

+1
source share
3 answers

The method is indeed selected by the type of runtime of the object. What is not selected by the runtime type is an entire field x . For object B there are two copies of x , one for Ax and one for Bx . You statically select a field from class A , since the compilation time type of the object returned by getObject is A This fact can be verified by adding a method to A and B :

 class A { public String print() { return "A"; } } class B extends A { public String print() { return "B"; } } 

and changing the test expression to:

 System.out.println(c1.getObject().print()); 
+10
source

If I am wrong, the default methods are virtual in java, so you override the method correctly. However, fields (for example, "x") are not virtual and cannot be overridden. When you declare "int x" in B, you are actually creating a completely new variable.

Polymorphism does not take effect for fields, so when you try to extract x on an object cast to type A, you will get 5, if the object is distinguished to type B, you will get 6.

+1
source

When fields in super and subclasses have the same name, they are called "hidden." Besides the issues mentioned in the question and answer, there are other aspects that can cause subtle problems:

From http://java.sun.com/docs/books/tutorial/java/IandI/hidevariables.html

In a class, a field that has the same name as the field in the superclass hides the field of the superclass, even if their types are different. Within a subclass, a field in a superclass cannot be referenced by a simple name. Instead, the field should be accessed via super, which is described in the next section. Generally speaking, we do not recommend hiding because it makes reading difficult.

Some compilers will warn you about hiding variables

+1
source

All Articles