从字节码看java中 this 隐式传参具体体现(和python中的self如出一辙,但是比python中藏得更深),也发现了 static 与 非 static 方法的区别所在!

  static与非static方法都是存储java的方法区。在static 方法中,没有this引用,因此无法使用当前类中所定义的变量,而非static方法则会默认传入this。我们今天就从另一个角度来真实看一下这个答案吧!

来个例子,并将其反编译为可视代码:

public class Hello {private final int ii;public Hello(int a) {ii = a;}public static void main(String[] args) throws Exception {sayHelloStatic("ok");}public void sayHello(String word) {System.out.println("hello, " + word);}public static void sayHelloStatic(String word) {System.out.println("static hello, " + word);}
}

反汇编命令:

javap -verbose Hello.class

反汇编结果:

Classfile /D:/xx/target/classes/com/xx/api/Hello.classLast modified 2018-11-8; size 1069 bytesMD5 checksum 9d39cd9d4e95588a73c059a4e69f01e8Compiled from "Hello.java"
public class com.xx.api.Hellominor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref          #14.#38        // java/lang/Object."<init>":()V#2 = Fieldref           #13.#39        // com/xx/api/Hello.ii:I#3 = String             #40            // ok#4 = Methodref          #13.#41        // com/xx/api/Hello.sayHelloStatic:(Ljava/lang/String;)V#5 = Fieldref           #42.#43        // java/lang/System.out:Ljava/io/PrintStream;#6 = Class              #44            // java/lang/StringBuilder#7 = Methodref          #6.#38         // java/lang/StringBuilder."<init>":()V#8 = String             #45            // hello,#9 = Methodref          #6.#46         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;#10 = Methodref          #6.#47         // java/lang/StringBuilder.toString:()Ljava/lang/String;#11 = Methodref          #48.#49        // java/io/PrintStream.println:(Ljava/lang/String;)V#12 = String             #50            // static hello,#13 = Class              #51            // com/xx/api/Hello#14 = Class              #52            // java/lang/Object#15 = Utf8               ii#16 = Utf8               I#17 = Utf8               <init>#18 = Utf8               (I)V#19 = Utf8               Code#20 = Utf8               LineNumberTable#21 = Utf8               LocalVariableTable#22 = Utf8               this#23 = Utf8               Lcom/xx/api/Hello;#24 = Utf8               a#25 = Utf8               main#26 = Utf8               ([Ljava/lang/String;)V#27 = Utf8               args#28 = Utf8               [Ljava/lang/String;#29 = Utf8               Exceptions#30 = Class              #53            // java/lang/Exception#31 = Utf8               sayHello#32 = Utf8               (Ljava/lang/String;)V#33 = Utf8               word#34 = Utf8               Ljava/lang/String;#35 = Utf8               sayHelloStatic#36 = Utf8               SourceFile#37 = Utf8               Hello.java#38 = NameAndType        #17:#54        // "<init>":()V#39 = NameAndType        #15:#16        // ii:I#40 = Utf8               ok#41 = NameAndType        #35:#32        // sayHelloStatic:(Ljava/lang/String;)V#42 = Class              #55            // java/lang/System#43 = NameAndType        #56:#57        // out:Ljava/io/PrintStream;#44 = Utf8               java/lang/StringBuilder#45 = Utf8               hello,#46 = NameAndType        #58:#59        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;#47 = NameAndType        #60:#61        // toString:()Ljava/lang/String;#48 = Class              #62            // java/io/PrintStream#49 = NameAndType        #63:#32        // println:(Ljava/lang/String;)V#50 = Utf8               static hello,#51 = Utf8               com/xx/api/Hello#52 = Utf8               java/lang/Object#53 = Utf8               java/lang/Exception#54 = Utf8               ()V#55 = Utf8               java/lang/System#56 = Utf8               out#57 = Utf8               Ljava/io/PrintStream;#58 = Utf8               append#59 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;#60 = Utf8               toString#61 = Utf8               ()Ljava/lang/String;#62 = Utf8               java/io/PrintStream#63 = Utf8               println
{public com.xx.api.Hello(int);descriptor: (I)Vflags: ACC_PUBLICCode:stack=2, locals=2, args_size=20: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: aload_05: iload_16: putfield      #2                  // Field ii:I9: returnLineNumberTable:line 14: 0line 15: 4line 16: 9LocalVariableTable:Start  Length  Slot  Name   Signature0      10     0  this   Lcom/xx/api/Hello;0      10     1     a   Ipublic static void main(java.lang.String[]) throws java.lang.Exception;descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=1, locals=1, args_size=10: ldc           #3                  // String ok2: invokestatic  #4                  // Method sayHelloStatic:(Ljava/lang/String;)V5: returnLineNumberTable:line 42: 0line 45: 5LocalVariableTable:Start  Length  Slot  Name   Signature0       6     0  args   [Ljava/lang/String;Exceptions:throws java.lang.Exceptionpublic void sayHello(java.lang.String);descriptor: (Ljava/lang/String;)Vflags: ACC_PUBLICCode:stack=3, locals=2, args_size=20: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;3: new           #6                  // class java/lang/StringBuilder6: dup7: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V10: ldc           #8                  // String hello,12: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;15: aload_116: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;19: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;22: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V25: returnLineNumberTable:line 48: 0line 49: 25LocalVariableTable:Start  Length  Slot  Name   Signature0      26     0  this   Lcom/xx/api/Hello;0      26     1  word   Ljava/lang/String;public static void sayHelloStatic(java.lang.String);descriptor: (Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=3, locals=1, args_size=10: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;3: new           #6                  // class java/lang/StringBuilder6: dup7: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V10: ldc           #12                 // String static hello,12: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;15: aload_016: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;19: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;22: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V25: returnLineNumberTable:line 51: 0line 52: 25LocalVariableTable:Start  Length  Slot  Name   Signature0      26     0  word   Ljava/lang/String;
}
SourceFile: "Hello.java"

我们从字节码文件中可以看出来:

  sayHello(String word) 和 sayHelloStatic(String word) 都只有一个参数,但是在字节码中:

    sayHello(String word) 中引用 word 时使用了 15: aload_1, 可以看出其加载的变量是在 slot1中,而 slot0中即保存了 this 。

    sayHelloStatic(String word) 中引用 word 时使用了 15: aload_0, 可以看出静态方法中,直接将变量存在了 slot0中,因此无法使用 this 中的变量了。

在LocalVariableTable 本地变量表中,可以清楚地看到,哪个slot存储了什么变量。

  当要操作当前类的变量或方法时,需要先 aload_0, 然后再做相关操作!

从字节码看java中 this 的隐式传参相关推荐

  1. 7.Java中变量的隐式转换以及强类型转换

    1.变量的相加,(变量的数据类型一致),直接运算即可!          结论:         Java中变量的 隐式转换(数据类型的默认类型提升)         byte,short,char- ...

  2. Java生产环境下性能监控与调优详解 第8章 JVM字节码与Java代码层调优

    第8章 JVM字节码与Java代码层调优 8-1 jvm字节码指令-1 8-2 jvm字节码指令-2 8-3 i++与++i 8-4 字符串+拼接 8-5 Try-Finally字节码 8-6 Str ...

  3. js onclick传参对象_js中onClick([object object])的传参问题。跪求!

    你的位置: 问答吧 -> JavaScript -> 问题详情 js中onClick([object object])的传参问题.跪求! 问题是这样的,看代码 for(var i=0;i ...

  4. sql server 中的数据类型隐式转换

    数据类型转换分为隐式转换和显示转换 1)显示转换顾名思义使用函数进行数据类型转化,如cast.convert cast 和convert的区别 CAST( expression AS data_typ ...

  5. python调用so库输出传入指针_python中使用ctypes调用so传参设置遇到的问题及解决方法...

    问题 近日在做一组声纹聚类时,使用了另一团队同学开发的声纹距离算法.该算法对外提供的是一组so包,需要使用方自己去使用.在python中调用纯so包一般使用ctypes类库,用起来看起来简单但也有不少 ...

  6. 怎么看java中ide_如何在eclipse IDE中查看Java的字节码?

    Eclipse的默认类文件查看器显示源(参见VonC的答案),如果它已经与二进制文件相关联,否则给出类的javap样视图(具有附加源的选项).我猜这是你正在寻找的后者. 我从来没有找到一种方法来干净地 ...

  7. 从字节码看 finally关键字、异常表

    大家好,我是烤鸭: 今天说下 finally 这个关键字. 1.  认识finally finally 总是跟 try.catch一起出现,finally是执行方法结束一定要执行的代码,比如流关闭等等 ...

  8. java自带的字节码技术_读懂字节码-还原JAVA源码

    已知有两个类: public class Father extends GrandFather { public String name = "father"; public vo ...

  9. java char是几个字节_关于java中char占几个字节,汉字占几个字节

    我们平常说,java中char占2个字节,可又说汉字在不通的编码格式中所占的位数是不同的,比如gbk中汉字占2个字节,utf8中多数占3个字节,少数占4个.而所有汉字在java程序中我们都可以简单的用 ...

最新文章

  1. 《Redis设计与实现》之第四章:字典
  2. 干货 | 架构师入门实战视频课程(一)
  3. python网络编程案例_Python 网络编程_python网络编程基础_python高级编程
  4. centos7防火墙firewalld配置,干货直接上手
  5. 【echarts】echarts开发流程详解
  6. 前序-中序-后序-非递归-实现
  7. IAAS: IT公司去IOE-Alibaba系统构架解读
  8. 如何在myeclipse中导入jar包?
  9. java8 内存设置_Java 8内存分析
  10. 基于深度学习的自然场景文字检测及端到端的OCR中文文字识别
  11. LeetCode 1004. 最大连续1的个数 III(双指针+滑动窗口)
  12. 显示浏览器表单输入框的缓存密码
  13. DBA日常管理——数据归档(Archiving-Data)
  14. java定义不同类型参数_java – Mockito允许使用不同的参数类型来模拟重载方法
  15. 对话阿里 CTO 程立:未来数字世界的根基是开源和云
  16. hscan扫描mysql代码_HScan 扫描器
  17. 代码与国家地区对照表
  18. 数据结构第一章概论习题及答案
  19. python拼图_利用python制作拼图小游戏的全过程
  20. 白浩然计算机学院,信息数理学院2015年上半年团员推优汇总表.doc-附件:.doc

热门文章

  1. ++[[]][+[]]+[+[]] == 10 //true
  2. windows 2012 r2 can't find kb2919355
  3. Linux常用到的指令汇总
  4. winform实现word转换为PDF(.doc)
  5. 今天被BSE指摘了2个问题,感觉很典型
  6. 删除所有的.svn 文件
  7. JUnit5 断言示例
  8. 前端快速开发插件emmet,炫技必备
  9. 程序的编译与链接、预处理符号、指令
  10. linux锁定账号 让其不能修改密码,passwd - 用于让用户可以更改自己的密码