Java 覆盖等于()
当运行这部分代码时,为什么我得到的是“O”而不是“p”Java 覆盖等于(),java,overriding,Java,Overriding,当运行这部分代码时,为什么我得到的是“O”而不是“p” class Pop{ @Override public boolean equals(Object o){ System.out.print("O"); return false; } public boolean equals(Pop p){ System.out.print("P");
class Pop{
@Override
public boolean equals(Object o){
System.out.print("O");
return false;
}
public boolean equals(Pop p){
System.out.print("P");
return false;
}
public static void main (String[] args)
{
Pop p1 = new Pop();
Object o = p1;
o.equals(p1);
}
}
下面是编写代码
o.equals(p1)
时发生的情况:
o
的类型,并看到它是Object
,因为这就是您声明的类型。它不会知道这是一个Pop
。就编译器而言,它可以是任何类型的对象。(通过查看前面的代码,您可以知道它将是一个Pop
,但编译器不会进行这种分析。)对象
类,查找等于
的匹配定义。equals只有一个定义,并且它匹配(即参数列表与定义兼容)。因此,Java字节码被创建为“我们正在调用对象中定义的方法equals
”
对象
中定义的方法equals
,如字节码所示。不过,Java在任何时候进行调用时,都会使用覆盖调用(如果有)。因此它查看实际类Pop
,并查看Pop
(或Object
和Pop
之间的任何其他超类,但这里没有超类)是否覆盖Object
中的该方法。Pop
中的第一个方法会覆盖它,因此执行的就是这个方法,“O”
会被打印出来。第二个equals
方法根本不被考虑,因为它不会覆盖对象中的equals
对象
时,其方法得到唯一的时隙;等于
的时隙可能是,比如说,7。因此,向量中的第7个条目将是等于的地址。当定义了Pop
时,由于第一个等于
覆盖了对象
中的一个,因此它也会得到插槽7。第二个等于
不会覆盖任何内容,因此它会得到一个新的插槽号,可能是18。因此会有一个向量,其中索引7包含中第一个等于的地址,而索引18包含第二个的地址。现在,当代码在对象
中调用等于
时,代码会说类似于“调用插槽7中的任何方法”。对于Pop
对象,插槽7中的方法将是第一个equals
,它将打印“O”
。但它从不看18号槽。我怀疑Java确实是以这种方式运行的,但效果是相似的。基本上,有一些ID可以被查找,并调用该ID的方法;Java在运行时不会搜索类中定义的可能被调用的另一个方法
更多:如果您真的想要它打印“p”
的行为,如果它的参数是Pop
,您可以这样做:
@Override
public boolean equals(Object o){
if (o instanceof Pop) {
return equals((Pop)o);
// this equals will be the one below, because of overload resolution
}
System.out.print("O");
return false;
}
因为重载解析(根据参数类型在方法中进行选择)是在编译时根据指定目标对象和方法参数的表达式的声明类型执行的。只有重写解析(根据调用它的对象的类型在给定签名的方法中进行选择)在运行时是动态发生的。Jashua Bloch在他的《有效Java》一书中正好论述了这种情况。[你可以在下面的答案中找到解释]()因为你没有研究什么是
override
以及什么时候发生的?@JohnBollinger你的意思是获得Pop的equals方法,因为参数实际上是重载,而不是重写?谢谢!这真的很有帮助。