方法重载和覆盖中的编译时和运行时绑定

时间:2014-12-09 13:58:01

标签: java overloading override

根据我的理解:

类的private,final和static方法遵循编译时绑定,即将在编译时决定调用哪个方法。

但是,在运行时决定调用非私有实例方法。

这用来解决我迄今为止的所有问题。但是,我遇到了上述陈述没有得到正确输出的问题。

以下是代码:

class Item
{
    Integer size;
    Item(Integer size)
    {
      this.size=size;
    }
    public boolean equals(Item item2) //not overriding the method of Object class
    {
        if(this==item2)
        return true;
        return this.size.equals(item2.size);
     }

  }

public class Test 
{
    public static void main(String[] args)
     {
        Item itemA= new Item(10);
        Item itemB= new Item(10);
        Object itemC=itemA;
        System.out.println("|"+ itemA.equals(itemB) + "|" + itemC.equals(itemB)+ "|");
     }

}

输出它给出:| true | false |

我期望的输出:| true | true |

此处equals class Item方法未覆盖equals Object方法,但由于equals的方法签名不同而导致重载方法

问题:在调用itemC.equals(itemB)中,为什么调用Object类的equals方法。

据我说:itemC在运行时拥有class Item的对象,因此equals的{​​{1}}应该被调用。在运行时,Item class中有两个equals方法,一个是自己的,另一个是从Item class类继承的。因此,Object应该被调用而不是equals(Item),因为调用是equals(Object)

我到底在概念上错过了什么?

3 个答案:

答案 0 :(得分:0)

  

问题:在调用itemC.equals(itemB)中,为什么调用Object类的equals方法。

因为itemC的编译时类型是Object

在执行时根据目标对象的实际类型执行覆盖,但重载是在编译时根据目标的编译时类型执行的表达

如果您使用javap -c -v Test,则会看到涉及的两个方法调用:

常量池:

...
#6 = Methodref #2.#32    //  Item.equals:(LItem;)Z
#7 = Methodref #16.#33   //  java/lang/Object.equals:(Ljava/lang/Object;)Z
...

然后是main方法:

33: invokevirtual #6  // Method Item.equals:(LItem;)Z
...
40: invokevirtual #7  // Method java/lang/Object.equals:(Ljava/lang/Object;)Z

这样就显示了被调用方法的签名。执行该签名的实现取决于执行时间类型。因此,如果您覆盖equals(Object)中的Item,则会为itemC.equals(itemA)调用该覆盖。

答案 1 :(得分:0)

重载是在编译时确定的,而不是运行时。因此,itemC.equals(itemB)调用equals的{​​{1}}方法,因为Object变量的类型为itemC

答案 2 :(得分:0)

来自jls reg overloading

摘录

When a method is invoked (§15.12), the number of actual arguments (and any explicit type
arguments) and the compile-time types of the arguments are used, at compile time, to determine the 
signature of the method that will be invoked (§15.12.2). If the method that is to be invoked is an 
instance method, the actual method to be invoked will be determined at run time, using dynamic method 
lookup (§15.12.4). 

基于上述语句,itemC.equals(itemB)调用equals类的Object方法,因为在编译类型itemCObject