Java 如果覆盖一个类的子类中的字段,该子类是否有两个名称相同(类型不同)的字段?
我有三门课:Java 如果覆盖一个类的子类中的字段,该子类是否有两个名称相同(类型不同)的字段?,java,subclassing,jls,Java,Subclassing,Jls,我有三门课: public class Alpha { public Number number; } public class Beta extends Alpha { public String number; } public class Gama extends Beta { public int number; } 为什么要编译下面的代码?还有,为什么测试没有任何运行时错误就通过了 @Test public void test() { final
public class Alpha {
public Number number;
}
public class Beta extends Alpha {
public String number;
}
public class Gama extends Beta {
public int number;
}
为什么要编译下面的代码?还有,为什么测试没有任何运行时错误就通过了
@Test
public void test() {
final Beta a = new Gama();
a.number = "its a string";
((Alpha) a).number = 13;
((Gama) a).number = 42;
assertEquals("its a string", a.number);
assertEquals(13, ((Alpha) a).number);
assertEquals(42, ((Gama) a).number);
}
字段不能被覆盖;首先,它们不是以多态方式访问的——您只是在每种情况下声明一个新字段
它可以编译,因为在每种情况下,表达式的编译时类型都足以确定您所指的名为number
的字段
在现实编程中,您可以通过两种方式避免这种情况:
- 常识:阴影字段使代码更难阅读,所以不要这样做
- 可见性:如果将所有字段都设置为私有,子类无论如何都不会知道它们
Beta
和Gama
中的number
变量隐藏了超类的成员变量number
通过强制转换,您可以访问超类中的隐藏成员。当后继者具有与超类字段同名的字段时,它被称为-隐藏字段 Java的字段不支持多态性,并且不考虑字段的类型
class A {
String field = "A: field";
String foo() {
return "A: foo()";
}
}
class B extends A {
//B's field hides A's field
String field = "B: field";
String foo() {
return "B: foo()";
}
}
@Test
public void testPoly() {
A a = new A();
assertEquals("A: field", a.field);
assertEquals("A: foo()", a.foo());
B b = new B();
assertEquals("B: field", b.field);
assertEquals("B: foo()", b.foo());
//B cast to A
assertEquals("A: field", ((A)b).field); //<--
assertEquals("B: foo()", ((A)b).foo());
}
A类{
String field=“A:field”;
字符串foo(){
返回“A:foo()”;
}
}
B类扩展了A类{
//B的字段隐藏A的字段
String field=“B:field”;
字符串foo(){
返回“B:foo()”;
}
}
@试验
公共void testPoly(){
A=新的A();
资产质量(“A:字段”,A.字段);
assertEquals(“A:foo()”,A.foo());
B=新的B();
资产质量(“B:字段”,B.字段);
assertEquals(“B:foo()”,B.foo());
//B投给A
assertEquals(“A:field”,((A)b.field);//和?它是这样工作的。如果需要重写,应该使用setter/getter方法。公共字段几乎总是个坏主意。请参阅Java中的™ 教程