将子类强制转换为超类后调用方法的有趣行为

时间:2013-02-16 17:06:07

标签: java casting

class A { 
    int i = 1; 
    int f() { return i; } 
} 
class B extends A { 
    int i = 2;
    int @Override f() { return -i; }
} 
public class override_test { 
    public static void main(String args[]) { 
         B b = new B(); 
         A a = (A) b;               // Cast b to an instance of class A. 
         System.out.println(a.i);   // Now refers to A.i; prints 1; 
         System.out.println(a.f()); // Still refers to B.f(); prints -2; 
    } 
}

我想知道为什么a.f()仍然引用B.f()而a.i引用A.i.

提前感谢!

3 个答案:

答案 0 :(得分:2)

在java 字段不是多态的 ,这就是a.i引用A.i

的原因

虽然a.f()引用了B.f(),因为b是一个对象ob B,虽然您将其投放到A,但这意味着您将能够仅使用A中声明的那些方法。

但该对象仍为B类型。

因此,当您访问某个字段时,它基于引用类型,当您访问方法时,它基于对象类型

答案 1 :(得分:0)

简单规则是当你调用一个方法时,它将是实例类型(多态),在这种情况下,实例的类型为B,即使引用的类型为A

当你调用变量时,它将在引用的类型上。

详细了解Ploymorphism

答案 2 :(得分:0)

就是这样。用C ++术语来说,Java实例方法调用是虚拟的。选择的方法取决于目标对象的实际类,而不是对其的引用类型。字段引用不是虚拟的,字段的选择取决于引用的类型。

我通常将字段保密或受保护,并通过方法而不是直接外部访问字段