public class Test {
public static void main(String[] args) {
B b = new B();
b.test();
}
}
class A {
String aString = "a";
void test() {
System.out.println(aString);
}
}
class B extends A {
String aString = "b";
}
为什么不能输入"B"? 我只是认为b.test()
会调用超类的方法,所以 b 会用户超类的属性。
为什么不能输入"b"? 我只是认为
b.test()
会调用superClass的方法,所以b会用户superClass的属性。
Java 类和实例变量可以继承,但它们不是虚拟的。 也就是说,Java 代码中出现的所有变量标识符都在编译时解析 - 它们没有动态解析。
因此,方法A.test()
中标识符aString
的外观在编译时解析为类A
的aString
属性。 这是该方法的所有调用都将访问的属性,而不考虑调用该方法的对象的实际类。 如果要在类 B 的实例上调用test()
时使用该类的属性,请在类A
和B
中提供 getter 方法,并A.test()
通过这些方法获取字符串。
b 中的变量隐藏了 a 中的变量。您可以通过删除 b 中的类型来修复它
class B extends A {
public B () {
aString = "b";
}
}
class A { String aString = "a"; void test() { System.out.println(aString); } } class B extends A { String aString = "b"; }
为 B 创建 2 个aString
变量。虽然A
不知道B
扩展它,但B
总是可以使用super
关键字从其父类A
访问"事物"。所以当你在B
中时,你可以使用aString
和super.aString
,它们将引用 2 个不同的变量:
class Ideone {
public static void main (String[] args) {
A a=new A();
B b=new B();
a.test();
b.test();
b.suptest();
}
static class A {
String aString="A.aString set from A";
void test() {
System.out.println("A.test(): "+aString);
}
}
static class B extends A {
String aString="B.aString set from B";
{
super.aString="A.aString set from B";
}
void test() {
System.out.println("B.test(): "+aString);
}
void suptest() {
System.out.print("B.suptest() calling super.test(): ");
super.test();
}
}
}
您可以在IdeOne上试用,产生输出
A.test(): A.aString set from A B.test(): B.aString set from B B.suptest() calling super.test(): A.test(): A.aString set from B
前两行没有显示任何花哨的东西,A.aString
和B.aString
都包含它们的初始值.
但是第三行输出显示super.test()
调用B
实际上在A.test()
中"结束",并且B
中的初始值设定项块确实改变了继承的aString
字段。
(旁注:static class
魔术与包含在单个文件中的示例有关,它不会影响继承部分)
你是对的。
由于Class A
和方法test()
不是抽象的,并且该方法test()
未被其subClass B
覆盖,因此即使您从B
实例调用它,返回也将完全按照Class A
中指定的方式。