`
xieyj
  • 浏览: 103127 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

java中调用接口及调用继承类效率区别

阅读更多

  都说调用接口要比调用继承类要慢,但慢在何处?

  先看byteCodeInterpreter.cpp里面对这invokevirtual和invokeInterface的区别。

        CASE(_invokeinterface): { //调用接口
        u2 index = Bytes::get_native_u2(pc+1);

        ConstantPoolCacheEntry* cache = cp->entry_at(index);

        methodOop callee;
        klassOop iclass = (klassOop)cache->f1();
        int parms = cache->parameter_size();
        oop rcvr = STACK_OBJECT(-parms);
        CHECK_NULL(rcvr);
        instanceKlass* int2 = (instanceKlass*) rcvr->klass()->klass_part();
        itableOffsetEntry* ki = (itableOffsetEntry*) int2->start_of_itable();
        int i;
        for ( i = 0 ; i < int2->itable_length() ; i++, ki++ ) {//搜索整个接口表,进行比较,直至找到
          if (ki->interface_klass() == iclass) break;
        }

        .......

        int mindex = cache->f2();
        itableMethodEntry* im = ki->first_method_entry(rcvr->klass());
        callee = im[mindex].method();//通过找到的接口,找到要调用的方法

   而invokevirtual(调用继承类)

       CASE(_invokevirtual):

          u2 index = Bytes::get_native_u2(pc+1);

          ConstantPoolCacheEntry* cache = cp->entry_at(index);

          methodOop callee;

          int parms = cache->parameter_size();

          instanceKlass* rcvrKlass = (instanceKlass*) STACK_OBJECT(-parms)->klass()->klass_part();

          callee = (methodOop) rcvrKlass->start_of_vtable()[ cache->f2()]; //直接调用方法

  由上面可见,最大的区别就是接口调用每次都需要搜索接口表,而调用继承类可以直接找到。

  再看看权威书籍《深入java虚拟机》P336页给出的答案,“java虚拟机使用不同于类引用的操作码来调用接口引用的方法,这是因为java不能象使用引用那样,使用许多与方法表偏移量相关的假设。对于类引用来说,无论对象实际的类是什么,方法在方法表始终占据相同的位置。但对于接口引用来说,情况就不是这样了,位于不同类的同一个方法所占据的位置是不同的,尽管这些类实现同一个接口。”

  由此可知,调用接口引用方法可能要比调用类引用要慢。一般情况下,单个类实现的接口都不多,其实这方面的效率影响还是蛮小的

4
0
分享到:
评论
2 楼 ZangXT 2009-09-20  
有些性能要求比较高的系统会考虑这一点的,典型的如JPC,尽量避免使用接口。
1 楼 qianli-2010 2009-03-03  
 

相关推荐

    使用JNA替代JNI调用DLL,并解决内存溢出问题

    在Java中调用外部C/C++函数的传统方式是使用JNI(Java Native Interface)。然而,JNI的使用过程相对繁琐,涉及多个步骤,包括编写C/C++接口代码、编译DLL/SO文件等。相比之下,JNA(Java Native Access)作为一种更...

    Java调用存储过程的2种方法

    在Java中调用数据库中的存储过程是常见的操作之一,这不仅可以提高程序性能和代码可维护性,还可以更好地利用数据库的功能。根据提供的标题、描述以及部分内容,本文将详细介绍Java中调用存储过程的两种方法。 ####...

    java 调用存储过程

    Java作为广泛使用的编程语言,经常需要与数据库交互,因此理解如何在Java中调用存储过程是至关重要的。 在Java中调用存储过程主要通过JDBC(Java Database Connectivity)接口来实现。JDBC是Java中用来与各种数据库...

    java中存储过程的调用

    #### 在Java中调用存储过程 接下来,我们将在Java程序中调用上面创建的存储过程: ```java import java.sql.Connection; import java.sql.CallableStatement; import java.sql.SQLException; public class ...

    常见java求职面试题目

    依赖是最弱的关系,一个类使用另一个类的服务,如在类B中调用类A的方法。聚合表示整体与部分的关系,如订单类包含多个商品类。继承则是类之间的层次结构,子类继承父类的属性和方法,可以扩展或覆盖。 构造器...

    JavaScript与安卓交互之JS调用安卓方法

    这个类需要继承自`JavaObject`并添加`@JavascriptInterface`注解,确保在WebView中安全调用。例如: ```java import android.webkit.JavascriptInterface; public class JsBridge { @JavascriptInterface ...

    PDA扫描程序开发,Hbuilder中调用安卓广播扫描

    1. **创建广播接收器**: 在HBuilder中,新建一个Java类继承自`BroadcastReceiver`,并在类中重写`onReceive()`方法。这个方法会在广播被触发时执行。 2. **注册广播接收器**: 在AndroidManifest.xml文件中,声明你...

    Java调用明华RF读写器DLL文件过程解析

    在Java中调用明华RF读写器DLL文件需要使用JNI(Java Native Interface)或者JNA(Java Native Access)的方式。这里我们使用JNA来调用DLL文件。首先,在pom.xml文件中添加JNA的依赖,搜索jna并选择jna:5.4.0或者jna...

    JAVA面向对象编程测试题.doc

    super 是 JAVA 中调用父类的构造方法或被隐藏的方法的关键字。 本资源摘要信息涵盖了 JAVA 面向对象编程中的一些重要知识点,涵盖了变量类型、运算符、控制语句、函数和继承等方面,为学习 JAVA 的人提供了有价值的...

    java对象和类知识点.doc

    面向对象编程是Java的核心特性,主要体现...它可以在构造函数中调用来调用其他构造函数,也可以在方法中访问当前类的属性和方法。需要注意的是,`this`不能在静态上下文中使用,因为静态成员属于类,而不属于类的实例。

    调用CUI程序的方法

    在Java中调用外部程序(如CUI程序)通常可以通过`Runtime`类来实现。`Runtime`类提供了运行时系统的一个接口,允许执行当前运行环境中的外部进程。在给定的代码片段中,作者演示了如何使用`Runtime.getRuntime()....

    Java 30道面试题及答案.docx

    6. **CallableStatement**:在JDBC中调用存储过程通常使用CallableStatement,它可以处理存储过程的输出参数和结果集。 7. **连接池**:连接池管理数据库连接,提高性能,减少资源消耗。常用的连接池实现有C3P0和...

    java基础理解Java中的类和对象.docx

    本文介绍了Java中的类和对象的基础知识,包括对象的概念、类的定义、如何创建和使用对象,以及通过具体的例子展示了继承的应用。通过这些基础知识的学习,可以更好地理解和掌握面向对象编程的核心思想,并将其应用于...

    jdbc调用存储过程,函数,游标

    在JDBC中调用存储过程通常涉及以下步骤: 1. 加载并注册数据库驱动,建立数据库连接。 2. 创建CallableStatement对象,它继承自PreparedStatement,专门用于调用数据库的存储过程。 3. 使用CallableStatement的`{}`...

    oracle如何使用java source调用外部程序

    本篇将介绍如何利用Java Source在Oracle中调用外部程序,并通过一个具体的示例来详细阐述整个过程。 首先,我们需要创建一个Java Source,这是在Oracle数据库内部执行Java代码的基础。Java Source是一个包含Java类...

    Java数据库程序中的存储过程设计

    为了在Java中调用存储过程,可以使用`CallableStatement`接口。`CallableStatement`继承自`PreparedStatement`,特别适合用于调用数据库中的存储过程或函数。以下是一个简单的示例: ```java import java.sql....

    JavaMySape抽象类面向对象.doc

    - 子类的构造函数中调用了 `super(width, height)`,这是Java中调用父类构造器的语法,确保每个形状都有宽度和高度这两个基本属性。 5. **toString()** 方法: - 各个子类都重写了 `toString()` 方法,这是一个...

    Spring Data JPA调用存储过程实例代码

    为了在Spring Data JPA 中调用存储过程,我们需要创建一个Repository接口,继承自 `CrudRepository` 并添加相应的方法。每个方法对应一个存储过程,通过 `@Procedure` 注解指定存储过程名称,而方法参数对应存储过程...

    Android应用源码之aidl跨进程调用.zip

    在Android系统中,每个应用程序默认运行在自己的进程中,因此当需要在一个应用中调用另一个应用的服务时,就需要使用IPC。 首先,让我们来了解AIDL的基本结构。一个AIDL文件通常包含以下元素: 1. **接口声明**:...

Global site tag (gtag.js) - Google Analytics