`
ZangXT
  • 浏览: 117439 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

接口类型引用为何能调用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 除了挨着比较确定方法好像没有特别好的方法了。

分享到:
评论

相关推荐

    Object C调用c++例子

    然后,可以在`.mm`(Objective-C++)文件中实现对C++类的实例化和方法调用。 4. **Objective-C++文件(.mm)**: 当Objective-C需要调用C++代码时,需要将相应的.m文件改为.mm。这是一个Objective-C++文件,它可以...

    JAVA之Object类所有方法

    需要注意的是,不是所有类都能被克隆,需要实现`Cloneable`接口才能避免抛出`CloneNotSupportedException`。 5. **finalize()**: 当垃圾收集器确定回收对象之前,会调用此方法,允许执行清理操作。然而,不应依赖此...

    unity3d中js调用C#类,混合调用

    `CallFunction`需要传递函数名和参数,`UnityObject`则需要先获取C#对象的引用,然后通过`SendMessage`或`Invoke`来调用方法。 6. **类型转换**: 由于JavaScript和C#之间的类型系统不同,所以在两者之间传递数据...

    Object类和Scanner类

    除了 `Object` 类之外,给定内容中还提到了 `Scanner` 类,这是一个用于读取简单数据类型(如整数、浮点数)以及字符串的基本类。`Scanner` 类位于 `java.util` 包中,常用于控制台输入处理。尽管没有给出具体示例...

    Java程序设计:020611_Object类.ppt

    - 在接口和实现类的例子中,接口A的实例可以被赋值给Object类型的变量,然后再转换回接口类型,展示了Java的多态性。 理解并掌握Object类的这些核心方法对于进行面向对象的Java编程至关重要。`toString()`和`...

    反射动态调用DLL方法,含参数

    反射是.NET框架提供的一种机制,它允许在运行时检查类型信息,包括类、接口、枚举、属性、方法等。通过System.Reflection命名空间中的类,如Assembly、Type、MethodInfo、ConstructorInfo等,我们可以动态地创建对象...

    C#调用Java接口演示

    这可能涉及加载Java类库,然后使用`JavaType`和`JavaObject`来实例化和调用Java接口。 5. **错误处理和异常转换**:由于C#和Java的异常处理机制不同,需要适当地处理和转换可能出现的异常,确保在两种语言间顺畅地...

    c#中调用com组件

    - **调用方法**:像操作任何其他.NET对象一样调用该对象的方法。 下面是一个简单的示例代码,展示如何在C#中使用一个假想的COM组件: ```csharp using System; using YourComNamespace; // 替换为实际的COM组件...

    C#.NET_动态调用webservice的三种方式

    一旦编译成功,我们可以通过反射来调用生成的代理类中的方法: ```csharp if (results.Errors.Count == 0) { Assembly assembly = results.CompiledAssembly; Type proxyType = assembly.GetType(...

    C#调用WebService接口

    总结,C#调用WebService接口涉及的知识点包括:WebService的基本概念,C#的添加服务引用,使用代理类,配置和服务实例化,异步调用,错误处理,以及WSDL和SOAP的理解。掌握这些知识点,开发者可以有效地在C#应用程序...

    JavaSE之Object与Object类

    需要注意的是,不是所有的类都能被克隆,需要实现`Cloneable`接口并覆盖`clone()`方法。 5. **finalize() 方法**: - `finalize()`方法在垃圾收集器准备回收对象前被调用,提供了一个清理资源的机会。然而,由于...

    C#调用C++封装的托管对象

    这个类需要包含公共接口,并且使用.NET的数据类型,以便C#能够理解。例如: ```cpp // MyManagedClass.h #pragma once using namespace System; public ref class MyManagedClass { public: void ManagedMethod...

    c#调用c++生成的dll文件中类方法

    总结来说,C#调用C++生成的DLL中的类方法涉及到跨语言互操作,通常需要通过C风格接口或C++/CLI作为中介。理解这两种方法的工作原理和限制,对于有效地在C#项目中集成C++代码至关重要。在实际开发中,需要根据项目的...

    基础接口调用开发完整实例

    通过这个基础接口调用的实例,我们可以学习到如何在C#中定义、实现接口,以及如何通过接口调用方法。同时,理解同步调用的工作原理,以及如何处理返回值和参数类,对于进行更复杂的系统集成和组件通信至关重要。

    VB6.0调用C# Dll解决方法

    这些方法应遵循公共接口、公共访问修饰符且为静态,因为VB6不支持实例化.NET对象。例如: ```csharp public class MyClass { [DllExport] public static int MyMethod(int input) { // 实现逻辑 } } ``` 2...

    CORBA动态接口调用

    DII允许在不知道接口的具体实现或对象引用的情况下调用方法。 6. 动态接收接口(Dynamic Skeleton Interface, DSI):DSI对应于服务器端,它提供了一种机制,使得服务器可以响应来自DII的动态调用。DSI允许服务器在...

    c++如何采用com组件的方法直接调用动态库

    方法一:使用 #import 导入类型库 使用 #import 导入类型库可以将 COM 组件的接口定义导入到 C++ 代码中。例如: ```cpp #import "D:\vomont\platform\bin\ZKDSDev\zkemkeeper.dll" no_namespace ``` 在头文件中...

    QT调用JS详细过程

    - **数据类型转换**:QT和JavaScript之间的数据类型可能不完全一致,需要注意数据类型的转换和兼容性问题。 #### 五、案例分析:从给定的部分内容中提取有效信息 根据题目给出的部分内容,我们可以看到JavaScript...

    Delphi7短信接口及短信接口调用案例demo

    1. **接口编程**:在Delphi中,接口是一种引用类型,它定义了一组方法但不提供实现。短信接口通常是由第三方短信服务提供商提供的,开发者需要按照接口规范来编写代码,以便调用其服务。接口允许你在不关心具体实现...

    Pb调用 c#编写的DLL

    总结来说,要让PowerBuilder调用C#编写的DLL,关键在于正确配置C#项目以支持COM互操作,生成具有正确标识的接口和实现类,然后在PB中通过COM接口调用这些类的方法。这种结合方式使得PB能够利用C#的高级特性,拓宽了...

Global site tag (gtag.js) - Google Analytics