2
public class Animal{

    int n = 5;

    public static void main(String[] args) {

        Animal a = new Animal();
        Animal ah = new Horse();
        Horse h = new Horse(); 

        System.out.println(h.n); // prints 7
        System.out.println(ah.n); // prints 5
        h = (Horse) ah;
        System.out.println(h.n); // prints 7

    }
}

class Horse extends Animal{

    int n = 7;

}

我的问题:

为什么h.n之后仍然打印 7 h = (Horse) ah?赋值后它应该指向同一个对象,ah并且 n 字段指向 5?

4

2 回答 2

8

首先,让我们n将类的字段称为AnimalAnimal.n”以避免混淆。

与方法不同,字段不受覆盖。所以在你的 Horse 类中,你可能认为你用 7 覆盖了值Animal.n,你实际上是在声明一个名为的新变量n(让我们调用它Horse.n以避免混淆)。

所以真的,你有一个Horse有两个字段的类:Animal.nHorse.n。当你说“”时你得到哪个字段n取决于当时变量的静态类型。

当您有一个类型为Horse但向上转换为的对象时Animal,该n字段引用Animal.n,并且值为“5”。因此ah.n是“5”。

当您拥有相同的对象时,再次向下转换为 a Horse,该n字段引用Horse.n,并且值为“7”。因此h.n是“7”。

澄清:确实,h确实指向指向的同一对象ah-向下转换不会改变所指向的对象。但是,静态类型确实会影响正在请求对象的哪个字段。

于 2011-02-06T01:35:36.490 回答
0

您在 Java 中创建的每个对象(称为实例)都指向创建它的类。这是对象的真实类型,并且在您对它进行引用时不会改变。同样,每个引用对象的变量都有一个声明的类型。这是编译器将如何处理对象并确定允许哪些操作的方式。

但是,这两种类型只是松散耦合的。转换对象引用仅更改声明的类型。它不影响对象的行为——只影响编译器如何处理它。

于 2011-02-06T04:56:33.610 回答