Although Java treats the fields and methods of a class analogously in many ways, method overriding is not like field shadowing at all. You can refer to shadowed fields simply by casting an object to an instance of the appropriate superclass, but you cannot invoke overridden instance methods with this technique.The following code illustrates this crucial difference:
class A{
//定义一个叫做A的类
int i = 1; //实例字段
int f(){return i;} //实例方法
static char g(){return 'A';} //类方法
}
class B extends A{
//定义A的子类
int i = 2; //隐含类A的字段i
int f() {return -i;} //覆盖类A的实例方法f
static char g() {return 'B';} //隐含类A的类方法g()
}
public class OverrideTest {
public static void main(String[] args) {
B b= new B(); //创建B类型的新对象
System.out.println(b.i); //引用B.i,打印结果为2
System.out.println(b.f()); //引用B.f(),打印结果为-2
System.out.println(b.g()); //引用B.g(),打印结果为B
System.out.println(B.g()); //这是调用B.g()的一种比较好的方法
A a = (A) b; //将b强制类型转换为类A的实例
System.out.println(a.i); //现在引用的是A.i,打印结果为1
System.out.println(a.f()); //仍然引用B.f(),打印结果为-2
System.out.println(a.g()); //引用A.g(),打印结果为A
System.out.println(A.g()); //这是调用A.g()的一种比较好的方法
}
}
While this difference between method overriding and field shadowing may seem surprising at first, a little thought makes the purpose clear. Suppose we have a bunch of
Circle and
Ellipse objects we are manipulating. To keep track of the circles and ellipses, we store them in an array of type
Circle[]. (We can do this because
Ellipse is a subclass of
Circle, so all
Ellipse objects are legal
Circle objects.) When we loop through the elements of this array, we don't have to know or care whether the element is actually a
Circle or an
Ellipse. What we do care about very much, however, is that the correct value is computed when we invoke the
area() method of any element of the array. In other words, we don't want to use the formula for the area of a circle when the object is actually an ellipse! Seen in this context, it is not surprising at all that method overriding is handled differently by Java than field shadowing.