鉴于以下代码:
public class A {
int at=2;
public int m(int i){return at+i;}
}
class B extends A {
int at=3;
public int m(int i){return at+5*i;}
}
public class Main {
public static void main(String args[]){
A x = new B();
System.out.println("Output "+x.m(x.at));
}
}
输出为13。
它是如何工作的? 我知道它需要来自B的方法,但是参数呢?
答案 0 :(得分:6)
看表达式:x.m(x.at)
。由于x
被归档为A
,x.at
将引用at
中的A
字段。
然而,在方法方面,它变得更加复杂。虽然x
被声明为A
,但x
实际上属于B
类型,因此方法m
将从x
的实践中调用class,B
。
也许this可以提供帮助。
答案 1 :(得分:3)
实际上,您有两个at
字段,其中一个在A
中声明,另一个在B
中声明。 m
中的方法A
引用at
中的字段A
; m
中的方法B
是指at
中提交的B
。方法被覆盖,字段不被覆盖。 x
被声明为A
的实例,因此x.at
为2.当您调用方法m
时,将调用重写的方法(B.m(2)
),以便获得3+ 5 * 2 = 13。
在这种情况下,Java Language specification应该告诉你什么是对的,为什么。可以在8.3. Field Declarations
中找到对此问题的回答如果类声明了具有特定名称的字段,那么 据说该领域的声明隐藏任何和所有可访问的 超类中具有相同名称的字段的声明,和 班级的超级接口。
如果使用限定名称(第6.5.6.2节),则可以访问隐藏字段 它是静态的,或者使用包含的字段访问表达式 关键字super(§15.11.2)或强制转换为超类类型。
强制转换为超类类型。
答案 2 :(得分:1)
变量不会覆盖类似方法。因此,变量值取决于引用变量,而不取决于此引用变量引用的实例。
示例:在您的情况下。在main()方法
中A x = new B();
引用变量x的类型为A,它包含类型B实例的引用。
因为X是A类型。当你写x.at时,它引用的是A类变量。