Java 为什么可以';重写不能在编译时完成,但重载可以吗?

Java 为什么可以';重写不能在编译时完成,但重载可以吗?,java,runtime,overriding,Java,Runtime,Overriding,我知道重载是在编译时完成的,因为指定了参数的数量和类型,并且编译器知道调用了对象中的哪个方法 但是在重写过程中,为什么编译器看不到超类中是否存在子类方法 如果编译器在编译时不知道类,那么它如何识别重载 谢谢 设身处地为编译器着想。假设您必须编译以下方法: public void foo(List<String> list) { System.put.println(list.size()); } 在编译时无法知道列表的具体类型。您只能在运行时知道。因此,只能在运行时决定调用

我知道重载是在编译时完成的,因为指定了参数的数量和类型,并且编译器知道调用了对象中的哪个方法

但是在重写过程中,为什么编译器看不到超类中是否存在子类方法

如果编译器在编译时不知道类,那么它如何识别重载


谢谢

设身处地为编译器着想。假设您必须编译以下方法:

public void foo(List<String> list) {
    System.put.println(list.size());
}
在编译时无法知道列表的具体类型。您只能在运行时知道。因此,只能在运行时决定调用哪个
size()
方法。

在编译时检查重写

看看这个:

class Base {
    public void myMethod() {}
}

class Derived extends Base {
    @Override // error!
    public void myMethod2() {}
}
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();
编译器检查
myMethod2
是否在基类中,而不是基类中,因此编译器会给出一个错误

但是,在运行时确定要调用的重写方法的版本。这是因为要确定调用哪个方法,必须知道对象的运行时类型。编译器无法知道变量的运行时类型,除非它运行您的代码,此时不再是“编译”时间

看看这个:

class Base {
    public void myMethod() {}
}

class Derived extends Base {
    @Override // error!
    public void myMethod2() {}
}
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:)。

“在重写为什么编译器看不到超类中是否存在子类方法”中,它只从子类中选择一个。您可能对注释感兴趣。@Andy Turner为什么不能在编译时选择?链接到Java 7 API文档,当然你可以以某种方式访问它。@Jamie请注意,
@Override
对运行时行为没有影响。它只是编译时的一个安全网,检查您的一个超类是否实际具有与您用
@Override
@Turing85注释的方法相同的签名。参数的具体类型可以是实现java.util.List的任何具体类。你怎么知道是哪一个呢?Java编译器就是这么做的。Java运行时根据列表的具体运行时类型选择要调用的具体方法(即ArrayList#size()、LinkedList#size()或WhateverOtherList#size())。这就是最神奇的地方。哦,这就是你的意思=)对不起。我以为你的意思是调用
foo(…)
。我的评论很快就会自我毁灭。@Turing85我澄清了我的意思。