zoukankan      html  css  js  c++  java
  • 方法重载与invokevirtual字节码指令的关系

    这次来看一下跟方法调用相关的东东,对于字节码而言跟方法调用的助记符有如下几个:

    • invokeinterface:调用接口中的方法,实际上是在运行期决定的,决定到底调用实现该接口的哪个对象的方法。
    • invokestatic:调用静态方法。【重要】
    • invokespectial:调用自己的私有方法、构造方法(<int>)以及父类的方法。
    • invokevirtual:调用虚方法,在c++中是存在虚方法这个概念的,但是Java是不存在的,但是在字节码中是存在有虚方法的,运行期动态查找的过程。【重要】
    • invokedynamic:动态调用方法。这是五个调用中最为复杂的,但是它是在JDK1.7之后才引用的,本身Java是一门静态的语言,但是通过一些引擎可以调用Javascript,这里了解一下既可。

    下面来用代码先来了解一下invokstatic助记符:

    接下来编译,然后用jclasslib查看一下字节码信息:

    其实这种静态方法的调用是属于静态解析,关于静态解析总共有4个情形:

    • 静态方法
    • 父类方法
    • 构造方法
    • 私有方法:【为啥不能是公有方法呢?因为公有方法是能够被父类重写的,既然存在重写就会存在多态的可能,而私有方法是不可能被子类重写的】

    以上4类方法称为非虚方法,他们是类加载阶段就可以将符号引用转换为直接引用的。

    接下来再来看另外一个程序,会得到另外一个理论化的东东:

    那程序的输出结果是什么呢?不卖关子了,直接看结果,其结果肯定会颠覆我们的眼睛:

    这逆天的结果是为啥呢?其实这里涉及到“方法的静态分派”的理论化的东东,下面来看一下这块的理论:

    对于这句代码而言:

    g1的静态类型是Grandpa【特别注意这个,既始我们强制类型转换也不会改变g1的静态类型,比如:(Father)g1】,而g1的实际类型(真正指向的类型)是Father,而变量的静态类型是不会发生变化的,而变量的实际类型是可以发生变化的(多态的一种体现),实际类型是在运行期方可确定的。而我们定义的三个test()方法其实是属于方法的重载,如下:

    重点来了:对于方法重载,其实它是一种静态的行为,既然是静态的行为,那么调用方法传的参数则会只认变量的静态类型,而非变量的实际类型,如下:

    这就是原因之所在,下面来查看一下它的字节码信息:

    关于Java的方法重载和重写最大的区别就在于:方法重载它是一个静态形为【也就是像咱们这个例子,在编译其就已经确定了】,而方法重写则是一个动态形为【在编译期确定不了,得到运行期才行】。

  • 相关阅读:
    jquery easy ui 1.3.4 窗口,对话框,提示框(5)
    jquery easy ui 1.3.4 布局layout(4)
    4.1 avd
    android sdk 安装排错
    推荐一个非常COOL的开源相册程序!
    JQuery LazyLoad实现图片延迟加载-探究
    Js和asp.net各自设置的cookie相互读取的方法
    js html5推送 实例
    给网页添加[回到顶部]和[去底部]功能
    Session赋值(备注)
  • 原文地址:https://www.cnblogs.com/webor2006/p/9723289.html
Copyright © 2011-2022 走看看