Java 扩展类上的重载方法

Java 扩展类上的重载方法,java,Java,简单的问题,奇怪的结果。我有两门课A和B: public class A { protected int num; public A(int n) { num = n; } public boolean f(A a) { return num == a.num * 2; } } 为什么y1.f(y2)调用A中的f()方法而不是B A y1 = new B(10); B y2 = new B(10);

简单的问题,奇怪的结果。我有两门课
A
B

public class A
{
    protected int num;

    public A(int n)
    {
        num = n;
    }

    public boolean f(A a)
    {
        return num == a.num * 2;
    }
}

为什么
y1.f(y2)
调用
A
中的
f()
方法而不是
B

A y1 = new B(10);
B y2 = new B(10);

System.out.println(y1.f(y2));
它不应该在
B
中调用
f()
,因为
B
A
更具体吗

为什么y1.f(y2)在A中而不是在B中调用f()方法

因为
y1
的编译时类型是
A

重载是在编译时执行的。。。调用方法的对象的执行时间类型仅与重写相关

因此,编译器正在选择方法
f(A)
,因为这是它知道它可以调用
y1
的唯一
f
方法(并且在参数列表中检查它是否适用)。该方法在
B
中未被重写,因此在执行时,调用
A
中的实现

作为一个较新的例子,请考虑这个代码:

Object x = "foo";
int length = x.length();

这甚至不会编译,因为
Object
不包含
length()
方法<代码>字符串,但是编译器不考虑,因为编译时类型<代码> x>代码>是代码>对象< /代码>,而不是<代码>字符串< /代码> -即使我们可以在执行时知道
x
的值将是对
字符串
对象的引用。

尽管@JonSkeet的答案总是毫无疑问的。。只是用字节码来支持这一点。。您还可以检查通过了什么方法,当您看到字节码
25:invokevirtual\27//method com/package1/A.f:(Lcom/p ackage1/A;)Z时,您可以看到编译代码
(y1.f(y2))
Object x = "foo";
int length = x.length();