关于java中的重写和向上转型问题

在讲成员方法重写时,变量调用的是子类重写后的方法还是父类的原方法,是由变量所指向的对象实例的类型决定,而不是由变量本身的类型决定。可是比如下图的程序,PrivOverride po=new Derived,这个po到底是父类类型还是子类类型呢?按照重写的规定,那么调用po.f()调用的应该是子类的f方法,那么这个po就应该是子类类型吧?可是按照向上转型的说法,这个po就是父类类型的,所以有点搞不清。。而且父类的f方法是private的,子类不能继承(子类是不能继承父类的private型的成员变量和方法的吧?),而子类又自己重新实现了一个public型的f方法,那么最后输出的时候为什么不输出子类重新实现的这个public型的f方法而是输出父类的f方法的结果呢?图片

首先,PrivOverride 中的方法f()是private的,方法f()对子类不可见,因而子类不能继承和重写方法f()。子类中的public void f()是一个新的方法,和基类中的方法无关。(@Override public void f()会报错,证明覆盖失败。)
再次,要理解向上转型的过程,向上转型过程中,子类型会保留和基类型接口相同的方法,丢失其它方法。本例中的子类方法并没有重写成功,即其方法与基类型接口不一样,PrivOverride po = new Derivied 转型为基类引用后,就不能调用public void f(),这个方法了,因为转型后丢失了
然后回到你的问题:po是基类类型,如果基类方法是public void f(),即子类成功覆盖基类方法(po向上转型时保留了子类接口),po.f()调用的才是子类方法,才能实现多态,否则po.f()调用的是基类方法。
因而你的第一句“变量调用的是子类重写后的方法还是父类的原方法,是由变量所指向的对象实例的类型决定,而不是由变量本身的类型决定。”,这句话不准确的。

 需要清楚的一点是重写必须是与父类的方法有一样的声明,但是实现不同,而且只能重写有访问权限的方法即可继承的方法。这点跟现实生活中的继承概念是一样的,有使用权才能再创造。

我们说一个类的类型,其实隐含的意思就是它也是它基类的类型。这不存在什么“转”的问题。中国人不需要转,他天然就是人。人不需要转,天然就是动物。
反过来不成立。将一个动物视作人,这不一定,不一定的事情需要程序员通过类型转换来确认。