invokespecial与invokevirtual指令的区别
package com.test19; class Father { public void publicMethod() { privateMethod(); // this是Son对象,调用Father的方法 Son son = (Son)this; System.out.println(son); this.privateMethod(); } private void privateMethod() { System.out.println("Father.privateMethod()"); } public void tm() { System.out.println("Father.tm()"); } } class Son extends Father { public void publicMethod() { System.out.println("Son.publicMethod()"); } public void tm() { super.tm(); finalMethod(); } public final void finalMethod() { System.out.println("Son.finalMethod()"); } } public class TestInvokeMethod { public static void main(String[] args) { Father test = new Son(); test.publicMethod(); // Son.publicMethod() } }
在运行时,this对象是Son,但是通过this.privateMethod()调用的是Father类的私有方法,因为运行时,invokespecial选择方法基于引用声明的类型,而不是对象实际的类型。但invokevirtual则选择当前引用的对象的类型。
当为子类添加public void privateMethod(){}方法时,仍然调用父类方法,没有任何影响。
以下情况使用invokespecial操作码:
1、init()函数,就是调用构造函数生产一个实例的时候。
2、私有方法
3、通过super.method()形式调用的方法
TestInvokeMethod.class
Constant pool: #1 = Methodref #6.#15 // java/lang/Object."<init>":()V #2 = Class #16 // com/test19/Son #3 = Methodref #2.#15 // com/test19/Son."<init>":()V #4 = Methodref #17.#18 // com/test19/Father.publicMethod:()V #5 = Class #19 // com/test19/TestInvokeMethod #6 = Class #20 // java/lang/Object #7 = Utf8 <init> #8 = Utf8 ()V #9 = Utf8 Code #10 = Utf8 LineNumberTable #11 = Utf8 main #12 = Utf8 ([Ljava/lang/String;)V #13 = Utf8 SourceFile #14 = Utf8 TestInvokeMethod.java #15 = NameAndType #7:#8 // "<init>":()V #16 = Utf8 com/test19/Son #17 = Class #21 // com/test19/Father #18 = NameAndType #22:#8 // publicMethod:()V #19 = Utf8 com/test19/TestInvokeMethod #20 = Utf8 java/lang/Object #21 = Utf8 com/test19/Father #22 = Utf8 publicMethod { public com.test19.TestInvokeMethod(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 28: 0 public static void main(java.lang.String[]); flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=2, args_size=1 0: new #2 // class com/test19/Son 3: dup 4: invokespecial #3 // Method com/test19/Son."<init>":()V 7: astore_1 8: aload_1 9: invokevirtual #4 // Method com/test19/Father.publicMethod:()V 12: return LineNumberTable: line 30: 0 line 31: 8 line 33: 12 }
Father.class
Constant pool: #1 = Methodref #4.#14 // java/lang/Object."<init>":()V #2 = Methodref #3.#15 // com/test19/Father.privateMethod:()V #3 = Class #16 // com/test19/Father #4 = Class #17 // java/lang/Object #5 = Utf8 <init> #6 = Utf8 ()V #7 = Utf8 Code #8 = Utf8 LineNumberTable #9 = Utf8 publicMethod #10 = Utf8 privateMethod #11 = Utf8 tm #12 = Utf8 SourceFile #13 = Utf8 TestInvokeMethod.java #14 = NameAndType #5:#6 // "<init>":()V #15 = NameAndType #10:#6 // privateMethod:()V #16 = Utf8 com/test19/Father #17 = Utf8 java/lang/Object { com.test19.Father(); flags: Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 public void publicMethod(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #2 // Method privateMethod:()V 4: aload_0 5: invokespecial #2 // Method privateMethod:()V 8: return LineNumberTable: line 6: 0 line 7: 4 line 8: 8 public void tm(); flags: ACC_PUBLIC Code: stack=0, locals=1, args_size=1 0: return LineNumberTable: line 12: 0 }
Son.class
Constant pool: #1 = Methodref #5.#15 // com/test19/Father."<init>":()V #2 = Methodref #5.#16 // com/test19/Father.tm:()V #3 = Methodref #4.#17 // com/test19/Son.finalMethod:()V #4 = Class #18 // com/test19/Son #5 = Class #19 // com/test19/Father #6 = Utf8 <init> #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 publicMethod #11 = Utf8 tm #12 = Utf8 finalMethod #13 = Utf8 SourceFile #14 = Utf8 TestInvokeMethod.java #15 = NameAndType #6:#7 // "<init>":()V #16 = NameAndType #11:#7 // tm:()V #17 = NameAndType #12:#7 // finalMethod:()V #18 = Utf8 com/test19/Son #19 = Utf8 com/test19/Father { com.test19.Son(); flags: Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method com/test19/Father."<init>":()V 4: return LineNumberTable: line 16: 0 public void publicMethod(); flags: ACC_PUBLIC Code: stack=0, locals=1, args_size=1 0: return LineNumberTable: line 18: 0 public void tm(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #2 // Method com/test19/Father.tm:()V 4: aload_0 5: invokevirtual #3 // Method finalMethod:()V 8: return LineNumberTable: line 21: 0 line 22: 4 line 23: 8 public final void finalMethod(); flags: ACC_PUBLIC, ACC_FINAL Code: stack=0, locals=1, args_size=1 0: return LineNumberTable: line 25: 0 }
final方法的调用也用invoke
invokespecial与invokevirtual指令的区别的更多相关文章
- JSP中的编译指令和动作指令的区别
JSP中的编译指令和动作指令的区别 1.编译指令是通知Servlet引擎的处理消息,而动作指令只是运行时的脚本动作 2.编译指令是在将JSP编译成Servlet时起作用,而动作指令可替换成JSP脚本, ...
- 『现学现忘』Docker基础 — 36、CMD指令和ENTRYPOINT指令的区别
目录 1.CMD指令和ENTRYPOINT指令说明 2.CMD指令只有最后一条生效的原因 3.CMD指令演示 4.ENTRYPOINT指令演示 5.总结 CMD指令和ENTRYPOINT指令作用都是指 ...
- LEA指令与MOV指令的区别——发现一本汇编好书
一.汇编语言中PTR的含义及作用mov ax,bx ;是把BX寄存器“里”的值赋予AX,由于二者都是word型,所以没有必要加“WORD”mov ax,word ptr [bx];是把内存地址等于“B ...
- 汇编中中括号[]作用以及lea和mov指令的区别
现在总结一下:其中牵扯到lea指令,mov指令,[] 一.lea指令:对于寄存器来说:第二个操作数是寄存器必须要加[],不然报错,这里lea就是取[寄存器]的值,如:mov eax,2lea ebx, ...
- HC-05与HC-06的AT指令的区别
蓝牙HC-05与HC-06对比指令集 高电平->AT命令响应工作状态 低电平->蓝牙常规工作状态 <重新上电表示完成复位> HC-05 可以主从切换模式,但是HC-06 ...
- AngularJS展示数据的ng-bind指令和{{}} 区别
在AngularJS中显示模型中的数据有两种方式: 一种是使用花括号插值的方式: 1 <p>{{text}}</p> 另一种是使用基于属性的指令,叫做ng-bind: 1 &l ...
- 蓝牙进阶之路 (002) - HC-05与HC-06的AT指令的区别(转)
蓝牙HC-05与HC-06对比指令集 高电平->AT命令响应工作状态 低电平->蓝牙常规工作状态 <重新上电表示完成复位> HC-05 可以主从切换模式,但是HC-06 ...
- include动作和include指令的区别
1. include指令在被导入页面时,会与原有的jsp代码完全融合,共同生成同一个Servlet:而include动作则会在原有的jsp代码使用include方法而被导入页面,所以includ指令在 ...
- mov指令和 add以及sub 指令的区别
比如 mov ax,ds 比如 [0],ds #经过上机实验 add,sub指令不能对段寄存器操作
随机推荐
- mysql图文安装教程(win7 32位 亲测)
一.下载mysql:http://www.mysql.com/downloads/ 弹出: 你需要有一个 Oracle Web 帐户,没有的话,注册一个: 勾选许可: 输入搜索条件: 下载MySQL ...
- 201521123035-个人作业4——alpha阶段个人总结
个人总结 在alpha 结束之后, 每位同学写一篇个人博客, 总结自己的alpha 过程: 第一部分 类别 具体技能和面试问题 现在的回答(大三) 语言 最拿手的计算机语言是一?,代码量多少?(偏前端 ...
- Paxos与zookeeper
1,什么是Paxos算法? Paxos算法是分布式计算领域中一个非常重要的算法,主要解决分布式系统如何就某个值(决议)达成一致的问题.一个典型的场景是分布式数据库的一致问题:如果分布式数据库的各个节点 ...
- WPF画辐射图
public void WriteLineCircle(double originX, double originY, double r, int lineCount,List<string&g ...
- javascript实现快排
<script> var a = [7,4,5,3,2,1,4,5,6,6,2,21,4,53,12,0,-5,31,535,64,11,1,1,1,1]; function swap(a ...
- linux中权限
$ ls -l /bin/bash -rwxr-xr-x 1 root wheel 430540 Dec 23 18:27 /bin/bash -rwxr-xr-x 包含该特殊文件的权限的符号表示.该 ...
- 【大数据之数据仓库】kudu性能测试报告分析
本文由 网易云发布. 这篇博文主要的内容不是分析说明kudu的性能指标情况,而是分析为什么kudu的scan性能会这么龊!当初对外宣传可是加了各种 逆天黑科技的呀:列独立存储.bloom filte ...
- Flask系列03--Flask的路由 app.route中的参数, 动态参数路由
Flask–路由 添加路由的两种方式 第一种 @app.route("/my_de") def detail() 第二种(了解即可) app.add_url_rule(" ...
- JQuery Mobile - 修改复选框的选中状态无效解决办法!
今晚,在编写JQuery Mobile程序时候,需要在代码里面控制复选框的选中状态,很简单的代码啊,很快完成了!等测试程序时候傻眼了,页面无论如何也不按照我写的代码显示出来!问题出在哪里呢?是我写的控 ...
- C#后端接收form-data,创建实体类
public class Para_list //实体类 { public long ParemeterID { get; set; } public string Name { get; set; ...