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

  • 相关阅读:
    win10 uwp 弹起键盘不隐藏界面元素
    win10 uwp 存放网络图片到本地
    win10 uwp 存放网络图片到本地
    sublime Text 正则替换
    sublime Text 正则替换
    win10 uwp 绘图 Line 控件使用
    win10 uwp 绘图 Line 控件使用
    AJAX 是什么?
    什么是 PHP SimpleXML?
    PHP XML DOM:DOM 是什么?
  • 原文地址:https://www.cnblogs.com/webor2006/p/9723289.html
Copyright © 2011-2022 走看看