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(f.a);
}
}
我得到输出b 3.为什么它不给b13作为输出。任何人都可以解释。
答案 0 :(得分:4)
假设类Foo声明如下
class Foo
{
public int a = 3;
public void addFive()
{
a += 5;
System.out.print("f ");
}
}
答案 1 :(得分:0)
在public int a = 8
班级而不是Foo
班级中声明Bar
它应该有效...打印 B 3 。
但我想您正在讨论Java认证考试中包含的问题,因此您必须更正Foo
类添加public int a = 3
的代码。
您无法在Java中覆盖变量,但在超类中声明为public
(或protected
),您也可以在所有继承的类中使用它。
在这种情况下,正确的输出是 B 13 ,因为在测试类中,您使用Bar
对象作为Foo
对象,因此值{{1 3 而不是 8 。
答案 2 :(得分:0)
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 ");
}
}
答案 3 :(得分:0)
我假设您打算在类a
中声明一个整数字段Foo
。
正如其他人所指出的那样,你的问题的答案与“覆盖”和“隐藏”的概念有关。解释它的另一种方法是,对于成员变量,没有“动态调度”这样的东西。这意味着,如果您访问某个对象的成员,系统会通过查看类层次结构来检查运行时的 您所指的成员。
因此,在调用方法f.addFive
时,系统会在运行时看到您的对象实际上是Bar
而不是Foo
,因此请{{1您在addFive
类中定义的函数。
对于成员变量不会发生这种情况:您在print语句中访问Bar
,在编译时决定在那里您想要访问字段{{1}在类f.a
中声明 - 所以,这就是在运行时会发生的事情。
现在,成员变量访问没有动态调度的原因是性能:每次你只需要查看整个'看看这是什么对象'的逻辑是非常昂贵的想要为成员变量添加一些值。