有关Java重载和动态绑定的问题
|
在下面的代码中,第一和第二个打印语句如何打印出SubObj?
top和sub指向同一个Sub类吗?
class Top {
public String f(Object o) {return \"Top\";}
}
class Sub extends Top {
public String f(String s) {return \"Sub\";}
public String f(Object o) {return \"SubObj\";}
}
public class Test {
public static void main(String[] args) {
Sub sub = new Sub();
Top top = sub;
String str = \"Something\";
Object obj = str;
System.out.println(top.f(obj));
System.out.println(top.f(str));
System.out.println(sub.f(obj));
System.out.println(sub.f(str));
}
}
上面的代码返回下面的结果。
SubObj
SubObj
SubObj
Sub
没有找到相关结果
已邀请:
6 个回复
你换
编译器仅“知道” top的类型为Top(又称引用类型)。因此,当您稍后编写时:
编译器“看到”调用\'top.f \'指的是Top类的f方法。它“知道” str是扩展对象的String类型。因此,由于1)调用\'top.f \'是指Top类的sf方法,2)Top类中没有使用String参数的f方法,以及3)由于str是Object的子类,因此顶级类的f方法是编译时唯一有效的选择。因此,编译器将str隐式转换为其父类型Object,因此可以将其传递给Top的f方法。 (这与动态绑定相反,在动态绑定中,上述代码行的类型解析将推迟到运行时,然后由JVM而非编译器解决。) 然后在运行时,在上面的代码行中,JVM将top转换为它的实际类型sub。但是,编译器已将参数str转换为Object类型。因此,现在JVM必须在类sub中调用f方法,该方法采用Object类型的参数。 因此,上面的代码行打印\“ subobj \”而不是\“ sub \”。 对于另一个非常相似的示例,请参见:Java动态绑定和方法覆盖 更新:在JVM的内部工作中找到了这篇详细的文章: http://www.artima.com/underthehood/invocationP.html 我对您的代码进行了注释,以使事情更加清楚:
疾桓
导致\“ Sub \”,例如,即使对子类型Top调用
\“ binds \”到匹配
的方法。 (这是在编译时确定的最佳合格签名)。虚拟调度本身是相同的。 快乐的编码。
玖料萄
Java编译器只关心对象top是Top类型,并且唯一可用的方法将Object作为参数。然后在运行时,它将调用实际实例化对象的f(Object)方法。 下一个调用的解释方式相同。 接下来的两个调用将按照您的预期进行解释。
体悉
并且只能调用该签名。 但是
既知道两个签名,也必须按参数类型进行选择。
耐扫鹤胶鞭
就是这样运作。 对于
:
对象尝试使用
类的
方法。现在在
类中有两个
方法,对传递的参数进行类型检查。由于类型是
,因此会调用
类的第二个
方法。 对于
: 您可以将其解释为与(1)相同,即类型为
,以便调用第一个
函数。 对于
: 这很简单,因为您正在调用
类本身的方法。现在,由于
类中有两个重载方法,因此在这里还要对传递的参数进行类型检查。由于传递的参数的类型为
,因此将调用第二个
方法。 对于
: 与3.相似,这里传递的类型是
,因此调用
类的第一个
函数。 希望这可以帮助。
膛嵌墒缅欠
您创建了sub的实例,然后将其强制转换为顶部,这使得它仅了解top中存在的方法。 最上面存在的方法是公共
现在该方法也被sub重载,因此当您创建sub实例并将其向上转换到顶部时,它将被调用。 另一种表达方式是 sub类型是外观类型,而top类型是实际类型,因为您将sub指定为top。 如果重载实际类型,您将以明显的类型调用方法,但是您将无法调用实际类型中不存在的任何方法