解释变量隐藏在这个Java代码中是如何工作的
考虑下面的代码
class A { int x = 5; void foo() { System.out.println(this.x); } } class B extends A { int x = 6; // some extra stuff } class C { public static void main(String args[]) { B b = new B(); System.out.println(bx); System.out.println(((A)b).x); b.foo(); } }
该计划的输出是
6 5 5
我理解前两个但是无法理解最后一个。 b.foo()如何打印5.B类将inheritancefoo方法。 但它不应该打印bx会打印什么? 到底发生了什么?
是的, B
类inheritance了foo
方法。 但是B
的变量x
隐藏了A
的x
; 它不会取代它。
这是一个范围问题。 A
的foo
方法只能看到范围内的变量。 范围中唯一的变量是A
的实例变量x
。
foo
方法在B
inheritance但未被覆盖。 如果您使用相同的确切代码显式覆盖foo
:
class B extends A { int x = 6; @Override void foo() { System.out.println(this.x); } }
然后,当x
引用时将在范围内的变量将是B
的x
,并且将打印6
。 虽然方法的文本是相同的,但由于范围的原因,引用是不同的。
顺便说一句,如果你真的想在B
类中引用A
的x
,你可以使用super.x
。
嗯,这是因为静态绑定。
1)Java中的静态绑定发生在编译时,而动态绑定发生在运行时。
2)私有方法,最终方法和静态方法和变量使用静态绑定并由编译器绑定,而虚拟方法在运行时基于运行时对象绑定。
3)静态绑定使用Type(Java中的Class)信息进行绑定,而Dynamic绑定使用Object来解析绑定。
4)使用静态绑定绑定重载方法,而在运行时使用动态绑定绑定重写方法。
字段在Java和具有相同字段名称的子类中不可覆盖,父类阴影“仅”父类的字段。
所以this.x
指的是当前类中定义的x
: A
。
结果: 5
。
更确切地说: foo()
方法由B
子类inheritance,但它并不意味着inheritance方法的行为将因引用的实例字段而改变,因为所述字段不可覆盖:引用的this.x
表达式foo()
方法中的Ax
字段继续引用Ax
。
这与之前的两个陈述完全相同:
B b = new B(); System.out.println(bx); // refers Bx -> 6 System.out.println(((A)b).x); // refers Ax -> 5 b.foo(); // refers under the hood Ax -> 5
rgettman的非常好的答案显示了如何克服隐藏在子类中的字段。
克服隐藏的替代方法依赖于将实例字段设为private
(建议使用)并提供返回值的方法。
通过这种方式,您可以从覆盖机制中受益,并且对于类的客户端,字段隐藏不再是问题:
class A { private int x = 5; int getX(){ return x; } void foo() { System.out.println(this.getX()); } } class B extends A { private int x = 6; int getX(){ return x; } }
在JAVA中 ,可以覆盖方法,而变量则不能。 因此,由于您的方法foo
未在B
被覆盖,因此它从A
获取成员变量。
你打电话时
b.foo();
它检查B
是否覆盖了方法foo()
,它没有。 然后它看起来是一个级别,超级类A
并调用该方法。
然后你调用了A
的foo()
版本然后打印出来
this.x
现在, A
看不到B
的x
版本。
为了解决这个问题,您必须覆盖B
的方法
class B extends A { int x = 6; @Override void foo() { System.out.println(this.x); } }
现在,打电话
b.foo();
将调用B
的foo()
版本,您将获得预期的结果。
- 表每子类inheritance关系:如何在不加载任何子类的情况下查询Parent类??? (hibernate)
- 我是否可以为每种不同类型的inheritance类使用静态变量的不同副本
- Spring Data JPA(Hibernate):如何仅使用其抽象超类中的字段来检索具体实体?
- Struts 2中的action-default包
- 可以在子类中重写超类中的私有方法吗?
- Java中的implements和extends关键字有什么区别
- 具有generics参数基础的Javagenerics参数
- 使用inheritance的Struts2 Convention插件结果
- 避免在Java中重复导入:inheritance导入?