通过超类引用调用子类方法

我有这样的代码:

String stringRef = new String("Java"); // (1) System.out.println("(2): " + stringRef.getClass()); // (2) System.out.println("(3): " + stringRef.length()); // (3) Object objRef = stringRef; // (4) // System.out.println("(5): " + objRef.length()); // (5) Not OK. System.out.println("(6): " + objRef.equals("Java")); 

为什么我不能在第(5)行中调用length() ); 哪个类将equals()在第(6)行中调用?

你不能这样做,因为子类的方法不在你的超类中。 在这种情况下,尽管String是Object的子类,因为未在java.lang.Object类中声明length(),因此无法在其实例上调用length。

但是equals()方法在字符串类中被覆盖,因此将调用字符串的equals()

Object上声明了Object因此你可以调用它; length不是。 编译器不会尝试确定objRef引用的确切对象类型; 它只适用于它是一个Object的知识。

Java编译器基于点运算符左侧表达式的静态类型静态地解析要调用的方法的签名。 多态和动态调度的概念仅适用于调用哪种重写方法的解析。

对于编译器, objRefObject一个实例,它没有任何名为length()方法。 另一方面, equals()是一个来自Object的方法,并在Stringinheritance,这就是程序正常运行的原因。

length()方法是Strings独有的。 通过将其分配给Object,Java不再知道它是String。

古老的陈词滥调:所有圆圈都是形状,并非所有形状都是圆形。

如果您执行以下操作,它将起作用:

 System.out.println("(5): " + ((String)objRef).length()); 

在这里首先将字符串转换为String,然后调用length()。

当你有一个Type引用时,你只能调用方法或访问Type公共和可见Type ,即Type自己的方法或Type s超类的公共方法。

在这种情况下,Object将方法定义为equals和许多其他方法,因此您可以使用它们。

它是引用的类型,而不是实际的对象,它定义了所有可以访问的方法。所以你不能使用超类引用访问子类方法,尽管你的超类引用持有子类对象。