Java中的方法重写与类变量重写

3

我刚刚尝试了一些Java类变量覆盖行为的示例代码。以下是代码:

class A{
  int i=0;

  void sayHi(){
    System.out.println("Hi From A");
  }
}

 class B extends A{
  int i=2;

  void sayHi(){
    System.out.println("Hi From B");
  }
}


public class HelloWorld {
 public static void main(String[] args) {
    A a= new B();
    System.out.println("i->"+a.i); // this prints 0, which is from A
    System.out.println("i->"+((B)a).i); // this prints 2, which is from B
    a.sayHi(); //  method from B gets called since object is of type B
  }
}

我无法理解以下两行代码的含义:

System.out.println("i->"+a.i); // this prints 0, which is from A
System.out.println("i->"+((B)a).i); // this prints 2, which is from B

即使对象是类型为 B,为什么 a.i 会打印 0 呢?并且为什么将其转换为 B 后会打印 2 呢?


如果您想覆盖类变量,请查看此链接:https://dev59.com/sXRB5IYBdhLWcg3wN1AQ#28263825 - Blip
谢谢,伙计。我知道如何做了。但我更想了解根本原因以及为什么会发生这种情况。在下面找到了答案。 - Amit.rk3
2个回答

4
i不是一个方法 - 它是一个数据成员。数据成员不会被覆盖,而是被"隐藏"。所以即使您的实例是一个B,它有来自AB的两个数据成员i。当您通过A引用访问时,您将获得前者,当您使用B引用(例如,通过显式强制转换)访问时,您将获得后者。
另一方面,实例方法的行为不同。无论引用的类型如何,由于实例是B实例,您将获得多态行为并打印字符串"Hi From B"

好的。当我们使用getter和setter时,这个问题就不会出现了。理想情况下,我们不应该直接访问类变量,对吧? - Amit.rk3
@Amit.rk3 是的,确实。 - Mureinik

2
即使A被初始化为new B(),变量仍然是A。如果你说
B a = new B();

您不会遇到那个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接