现在的位置: 首页 > 综合 > 正文

走进方法绑定

2013年11月06日 ⁄ 综合 ⁄ 共 2772字 ⁄ 字号 评论关闭
文章目录

转载自AJAVA:http://ajava.org/readbook/java/bcys/17186.html

方法绑定(method binding)指产生调用方法的内存地址、相关参数和本地变量的处理过程。在执行调用时,JVM根据这些信息,能够执行内存地址中代表该方法的代码。因为构造器是一种特殊方法,方法绑定当然包括构造器绑定。前面提到过,Java提供两种方法绑定,即静态绑定和动态绑定。静态绑定发生在编译期间,由编译器完成;而动态绑定发生在运行期间,由JVM完成。

1  静态绑定

因为静态绑定在编译期间完成,可以提高代码的执行速度。因而在一般情况下,凡是能够在编译期间解决地址引用的方法调用,都采用静态绑定。静态绑定的方法包括:

  ●       静态方法。

  ●       构造器。

  ●       私有方法。

  ●       用关键字super调用的方法,包括使用super()调用超类构造器和super.superMethod()调用超类方法。

为了提高程序的运行速度,考虑在可能的情况下,尽量使用以上方法和方法调用。

2  动态绑定

Java 中,除了以上四种方法外,由对象调用的方法都采用动态绑定。动态绑定在JVM执行代码期间产生,会减慢程序运行速度。但由于Java语言是一种动态链接语言,即所有代码,即使是静态绑定,都或多或少涉及到动态链接和引用,如下面将要讨论的参数装载和堆栈处理,以及invokespecial。这是为什么 Java程序的运行速度比C或者C++慢的主要原因之一。

3  走进绑定和调用

无论是静态绑定还是动态绑定,在处理调用时,都经历从符号引用(symbolic reference),转换成为直接地址引用,证实合法、装载对象和参数、使用堆栈,这样一个过程。

  ●       符号引用到直接引用——符号引用提供对方法的识别,包括类名、方法名和方法描述(参数、参数类型、个数,以及返回类型)。在执行绑定操作时,首先根据对方法的识别信息,搜索该方法的储存地址,产生对这个地址的直接引用。直接引用通常包括这个地址的指针,或者地址位移值(offset),使得它允许JVM在执行这个方法时迅速地找到内存位置。

  ●       证实合法——在绑定处理过程中,还必须验证方法的调用是否遵循Java语言的规定、请求调用指令是否可安全执行、请求调用是否合法。例如,一个私有方法必须由当前执行对象的方法才可调用。如果证实步骤没有通过,JVM将抛出非法调用异常。

  ●       装载对象和参数——如果是对象方法,对象引用和方法参数必须装载到堆栈;如果是静态方法,只需将参数装入堆栈。因为静态方法将不涉及任何对象。

  ●       使用堆栈——在调用时,JVM将为执行这个方法产生一个堆栈框(stack frame)。这个堆栈框包括储存本地变量的空间、操作堆栈,以及其他JVM在具体运行时需要的信息。本地变量和操作堆栈需要的字节数在编译期间就已确定,并且已装载到字节码文件中,所以JVM知道需要保留多少储存器空间。在调用过程中,根据不同的运算和操作,JVM对堆栈框执行入栈和出栈的操作。

4  invokespecial和invokevirtual

invokespecial 指静态绑定后,由JVM产生调用的方法。如super(),以及super.someMethod(),都属于invokespecial。而 invokevirtual指动态绑定后由JVM产生调用的方法,如obj.someMethod(),属于invokevirtual。

正是由于这两种绑定的不同,在子类覆盖超类的方法、并向上转型引用后,才产生了多态以及其他特殊的调用结果。运行时,invokespecial选择方法基于引用的类型,而不是对象所属的类。但invokevirtual则选择当前引用的对象。让我们通过具体例子来理解它们的含义和不同:

//这个程序存在本书配套资源目录Ch8名为InvokeTest.java

//demo: invokespecial vs. invokevirtual

class SuperClass5 {

        public String method() {

                    return "from SuperClass5...";

        }

        public void otherMethod() {

                  System.out.println("In SuperClass5 otherMethod()...");

                   //invokespecial例子

                  System.out.println("SuperClass5 otherMethod() calls method(): " +

                   method());

        }

 }

class SubClass5 extends SuperClass5{

        public String method() {

                  return "from SubClass5...";

        }

        public void subMethod() {

                   //call SuperClass5 method()

                   System.out.println("SubClass5 calls super.method(): " +

                   super.method());

         }

}

这个代码的驱动程序如下:

//invokespecial vs. invokevirtual test

public class InvokeTest {

   public static void main( String args[] ) {

      SubClass5 b = new SubClass5();

      SuperClass5 supper = b;                             //向上转型引用

      System.out.println(supper.method());//invokevirtual,当前引用的对象是b

      b.subMethod();

      b.otherMethod();

   }

}

其运行结果为:

from SubClass5...

SubClass5 calls super.method(): from SuperClass5...

In SuperClass5 otherMethod()...

SuperClass5 otherMethod() calls method(): from SubClass5...

抱歉!评论已关闭.