【问题标题】:Java method overriding and variable shadowingJava 方法覆盖和变量遮蔽
【发布时间】:2014-09-15 11:43:10
【问题描述】:
public class Circle {
    public float r = 100;
    public float getR() {
        return r;
    }
}

public class GraphicCircle extends Circle {
    public float r = 10;
    public float getR() {
        return r;
    }

    // Main method
    public static void main(String[] args) {
        GraphicCircle gc = new GraphicCircle();
        Circle c = gc;
        System.out.println("Radius = " + gc.r);
        System.out.println("Radius = " + gc.getR());
        System.out.println("Radius = " + c.r);
        System.out.println("Radius = " + c.getR());
    }

}

您好,我无法理解上述代码的输出。输出为:

Radius = 10.0
Radius = 10.0
Radius = 100.0
Radius = 10.0

我明白为什么 gc.r 是 10。我也明白为什么 gc.getR() 是 10(因为 GraphicCircle 中的 getR() 方法覆盖了 Circle 的 getR() 方法)。但我不明白为什么 c.r 是 100,而 c.getR() 是 10(当您像上面的代码那样将类型转换为祖先类时,我无法理解继承中会发生什么)。

【问题讨论】:

标签: java inheritance


【解决方案1】:

首先,字段r不是隐藏,而是隐藏

其次,关于覆盖方法的技术术语称为动态绑定。这仅仅意味着在运行时查找正在调用的方法时会查询实例的实际类。

另一方面,对于字段,我们有静态绑定。这意味着编译器已经解析了所有的字段访问,并且编译器只知道声明的类型

所以结论是:

System.out.println("Radius = " + c.r);

这将打印100.0,因为变量的类型是Circle,因此编译器将对字段Circle.r 的访问写入字节码。

【讨论】:

    【解决方案2】:

    您可以覆盖方法,而不是字段或类变量。所以getR() 被覆盖,它实际上显示了你所期望的。

    获取c.r 你访问的是circle 的类变量而不是GC。

    将类变量公开也是一个坏习惯。它们应该是私有的或至少受到保护并使用 getter 和 setter (more about private fields) 访问它们。

    【讨论】:

      【解决方案3】:

      方法调用在Java 中是虚拟的,这意味着调用来自对象实际类型的方法,而不管您用来访问对象的引用是什么类型。另一方面,直接字段访问不是虚拟的,因此您访问哪个r 将取决于您访问它的引用类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多