我有以下代码。

public class Parent {

    @Override
    public int hashCode() {
         return 0;
    }

}

public class Child extends Parent {

    public void test() {
        this.toString();
        this.hashCode();
    }

}

如您在上面的代码中看到的,Child从Object继承toString(),从Parent继承hashCode()。
Child#test的字节码操作如下。
ALOAD 0: this
INVOKEVIRTUAL Object.toString() : String
ALOAD 0: this
INVOKEVIRTUAL Child.hashCode() : int
RETURN

我认为,如果invokevirtual调用Object.toString(),则应调用Parent.hashCode()以获得一致性。
或先调用Child.hashCode(),然后再调用Child.toString()。

但是,仅当目标方法被Object继承时,invokevirtual才会保持其一致性。

仅在这种情况下,对象中的invokevirtual调用方法。对于其他情况,请在当前类中调用invokevirtual调用方法。

我想知道为什么会这样。

最佳答案

您是正确的,编译器的行为不合逻辑。但是此代码的效果与您建议的两种变体的效果相同。因此,这可能不是故意的行为,而是编译器代码长期演进的结果。其他编译器可能会生成不同的代码。

10-08 14:35