覆盖java中的变量

public class Foo { public int a = 3; public void addFive(){ a += 5; System.out.print("f "); } } 

 public class Bar extends Foo { public int a = 8; public void addFive(){ this.a += 5; System.out.print("b " ); } } 

 public class Test { public static void main(String args[]){ Foo f = new Bar(); f.addFive(); System.out.println(fa); } } 

我得到输出b 3.为什么它不给b13作为输出。任何人都可以解释。

假设类Foo声明如下

 class Foo { public int a = 3; public void addFive() { a += 5; System.out.print("f "); } } 
  1. 变量没有覆盖的概念。 他们只是掩盖了。
  2. 它是打印3,因为当您使用超类引用访问变量时,它只访问在超类中声明的变量。 请记住,超类对子类一无所知。
 class Foo { public void addFive() { a += 5; System.out.print("f "); } } 

你没有定义’a’变量,所以这个例子甚至没有编译。

正确代码:

 class Foo { public int a; public void addFive() { a += 5; System.out.print("f "); } } 

并查看链接https://stackoverflow.com/a/2464254/1025312

我假设您打算在类Foo声明一个整数字段a

正如其他人所指出的那样,你的问题的答案与“覆盖”和“隐藏”的概念有关。 解释它的另一种方法是,对于成员变量,没有“动态调度”这样的东西。 这意味着,如果您访问某个对象的成员,系统会在运行时通过查看类层次结构来检查您所指的成员。

因此,在调用方法f.addFive ,在运行时,系统将看到您的对象实际上是一个Bar而不是Foo ,因此请使用您在Bar类中定义的addFive函数。

成员变量不会发生这种情况:你在print语句中访问fa ,并且在编译时决定在那里你想要访问在Foo类中声明的字段 – 所以,这就是在运行时会发生的事情时间。

现在,成员变量访问没有动态调度的原因是性能:每次只想为成员变量添加一些值时,要经历整个’看看这是什么对象’的逻辑是非常昂贵的。

Foo类中声明public int a = 8而不是Bar类它应该可以工作…打印B 3

但是我想你正在谈论Java认证考试中包含的一个问题,所以你必须纠正添加public int a = 3Foo类的代码。

您不能在Java中覆盖变量,但在超类中声明为public (或protected ),您也可以在所有inheritance的类中使用它。

在这种情况下,右输出是B 13,因为在测试类中,您使用Bar对象作为Foo对象,因此a值为3而不是8