我知道重载是在编译时完成的,因为指定了参数的数量和类型,编译器知道对象中的哪一个方法被调用。
但是在重写为什么编译器不会看到子类是否存在于超类中?
如果编译器在编译时不知道类,那么它如何识别重载?
谢谢!
答案 0 :(得分:8)
让自己置身于编译器之中。想象一下,你必须编译以下方法:
public void foo(List<String> list) {
System.put.println(list.size());
}
你怎么可能知道list
的具体类型是什么,从而调用size()
方法的具体实现?它是一个ArrayList吗?一个LinkedList?一个CopyOnWriteArrayList?你不能知道。
如果您还不相信,该方法的调用者可以执行类似
的操作if (Math.random() > 0.5) {
foo(new ArrayList<>());
}
else {
foo(new LinkedList<>());
}
在编译时无法知道列表的具体类型是什么。您只能在运行时知道。因此,调用哪个size()
方法只能在运行时决定。
答案 1 :(得分:2)
在编译时检查覆盖 !
看看这个:
class Base {
public void myMethod() {}
}
class Derived extends Base {
@Override // error!
public void myMethod2() {}
}
编译器检查myMethod2
是否在基类中,它不是,因此编译器会给出错误。
但是,决定在运行时确定要调用的重写方法的版本。这是因为要确定要调用哪个方法,必须知道对象的运行时类型。编译器无法知道变量的运行时类型,除非它运行您的代码,此时它不再编译&#34; -time ...
看看这个:
class Base {
public void myMethod() {}
}
class Derived extends Base {
@Override
public void myMethod() {}
}
// ...
Base obj;
if (Math.random() > 0.5) {
obj = new Derived();
} else {
obj = new Base();
}
obj.myMethod();
矛盾证明:
如果要在编译时决定要调用的方法的版本,那么此处的myMethod()
调用将始终在运行时调用相同版本的方法,无论您运行代码多少次。但是从if语句中,我们可以看到根据条件调用更改的方法。但是这种情况因代码的不同运行而异。这会产生矛盾,因此必须在运行时确定要调用的版本。 QED:)。