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指令不能对段寄存器操作
随机推荐
- Windows could not set the offline local information.Error code:0X80000001解决方法
我的笔记本是联想Y460(白色) 昨天在重装系统的时候遇到如下错误:Windows could not set the offline local information.Error code:0X8 ...
- Swift中的闭包(Closure)[转]
闭包在Swift中非常有用.通俗的解释就是一个Int类型里存储着一个整数,一个String类型包含着一串字符,同样,闭包是一个包含着函数的类型.有了闭包,你就可以处理很多在一些古老的语言中不能处理的事 ...
- 几个CSS-content的小例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- SoC FPGA开发板的FPGA配置数据下载和固化
小梅哥编写,未经许可,严禁用于任何商业用途 2018年7月2日星期一 soc fpga的烧写和固化方式与传统的纯fpga固化方式即存在形式上的相同,也存在细节上的差异,特整理此文. AC501-So ...
- vim 安装vim-javascript插件--Vundle管理
最近看了一下node.js,但是写的时候,vim对js没有很好的提示.于是就安装插件来处理,准备安装vim-javascript.但是安装github上面的插件时,推荐用Vundle和pathogen ...
- 微软儿童编程技术,kodu(酷豆)为儿童创造一个游戏世界
受微软青年星火项目组的邀请,我和微软项目组的朋友参加了一场针对儿童编程的技术指导. 儿童和编程,本来是两个完全不靠边的词.在大家的常规思维中,编程一直是软件开发人员的事情,是高科技类型的工作,高不可攀 ...
- DBCC--CHECKIDENT
检查活或重置自增键的标识值,可以使用NORESEED 来检查当前标识值和标识列在表中的最大值. 如果当前标识值与表中数据冲突或希望将标识值重置到一个较小的值时,可以只用RESEED 来设置 DBCC ...
- BitAdminCore框架更新日志20180531
索引 NET Core应用框架之BitAdminCore框架应用篇系列 框架演示:http://bit.bitdao.cn 框架源码:https://github.com/chenyinxin/coo ...
- C# 32位程序,申请大内存,附dome(wpf),亲测可用
1.我是vs2017,在选装vs的时候,需要安装c++模块,因为申请大内存的必要exe存放在vc的某个目录(下面会给出详细的地址)下的 2.安装完成在vs的安装目录可找到这个文件,我是社区版本的,如果 ...
- day70 csrf简单用法 &Django ContentType
一. 什么是跨站请求伪造 CSRF def transfer(request): if request.method =='POST': from_ =request.POST.get('from') ...