接口类型引用为何能调用Object类的方法

    首先看这段代码:

interface InterfaceTest{
	void test();
}

public class Test implements InterfaceTest{
	public void test(){
		System.out.println("test");
	}
	public static void main(String[] args){
		InterfaceTest i = new Test();
		i.toString();
		i.test();
   }
}

 

 

     刚学Java的时候有这样的疑问,变量i是InterfaceTest 类型的,而InterfaceTest 中并没有声明toString()方法,为什么可以通过编译呢?

 

    《The Java Programming Language》上这样介绍:

You can invoke any of the Object methods using a reference of an interface type because no matter what interfaces the object implements, it is always an Object and so has those methods. In fact, any interface that does not extend some other interface implicitly has members matching each of the public methods of Object (unless the interface explicitly overrides them).

      这里说的原因是接口中隐式的具有Object定义的方法成员。

《Java语言规范》有相似的说法:

If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.

      这里说的也是隐式声明。

      我想,如果是隐式声明的话,那就是编译器给加到接口里的。虚拟机调用这些方法的时候发生多态现象,根据对象的实际类型去查找这些方法。但实际上SUN 的jdk并非是这样实现的。

     反汇编一下,main方法的内容是:

0: new #5; //class Test
   3: dup
   4: invokespecial #6; //Method "<init>":()V
   7: astore_1
   8: aload_1
   9: invokevirtual #7; //Method java/lang/Object.toString:()Ljava/lang/String;
   12: pop
   13: aload_1
   14: invokeinterface #8,  1; //InterfaceMethod InterfaceTest.test:()V
   19: return

 

    注意这里直接用invokevirtual 来调用的Object中定义的方法。也就是编译器并没有像java语言规范说的那样工作。如果接口类型引用变量调用的是Object类的方法,编译器直接使用invokevirtual 来处理了。这样其实也无可厚非,首先,语义上的表现不受影响。其次,invokevirtual 比invokeinterface 具有更好的性能,因为invokevirtual可以根据索引直接定位方法,而invokeinterface 除了挨着比较确定方法好像没有特别好的方法了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值