Why isn't this method chosen based on the runtime-type of its object?

时光怂恿深爱的人放手 提交于 2019-12-11 09:21:37

问题


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 chooses a method based on the true type of its object. Here the true type is SubCovariantTest, which has defined an overriding method getObject.

The program prints 5, instead of 6. Why?


回答1:


The method is indeed chosen by the runtime type of the object. What is not chosen by the runtime type is the integer field x. Two copies of x exist for the B object, one for A.x and one for B.x. You are statically choosing the field from A class, as the compile-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());



回答2:


Unless I'm mistaken, methods are virtual in java by default, so you're overriding the method properly. Fields however (like 'x') are not virtual and can't be overriden. When you declare "int x" in B, you are actually creating a totally new variable.

Polymorphism doesn't go into effect for fields, so when you try and retrieve x on an object casted to type A, you will get 5, if the object is casted to type B, you will get 6.




回答3:


When fields in super and subclasses have the same names it is referred to as "hiding". Besides the problems mentioned in the question and answer there are other aspects which may give rise to subtle problems:

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

Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple name. Instead, the field must be accessed through super, which is covered in the next section. Generally speaking, we don't recommend hiding fields as it makes code difficult to read.

Some compilers will warn against hiding variables



来源:https://stackoverflow.com/questions/1918632/why-isnt-this-method-chosen-based-on-the-runtime-type-of-its-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!