java this关键字会造成事务失效_Java中,由this关键字引起的问题

好久以前一直有一个疑问,最近从新翻了遍JVM的书,才算是终于有所顿悟。问题以下:java

被本身遗忘的问题

1 packageorg.hanyan.test.testClass;2

3 public classT3AboutThis {4 public static voidmain(String[] args) {5 newSubT3().func();6 SuperT3 s = newSuperT3();7 System.out.println(s instanceof SubT3);//false

8 }9 }10

11 classSuperT3 {12 public String name = "Jack";13

14 protected voidfunc() {15 System.out.println(this.name);//Jack

16 System.out.println(this instanceof SuperT3);//true

17 System.out.println(this instanceof SubT3);//true

18 }19 }20 class SubT3 extendsSuperT3 {21 public String name = "Peter";22 }

一直没搞明白,上述代码中第17行为何打印出来的true。jvm

javap 打印了SuperT3类编译后的字节码指令以下:this

62d60c03b4d99f75501bf2a631bc8ffb.png

第1三、23字节的指令均为同一个引用变量,这个引用变量咱们能够在本地变量表中看到是Lorg/hanyan/test/testClass/SuperT3,spa

这里搞不明白为何1四、24字节的instanceof指令会返回一样的结果:truecode

目前怀疑是在运行中,jvm将本地变量this替换了。但这又引出一个问题,为何this.name中的this没有被替换?这个替换规则是怎么样的?blog

我自认为还算比较准确的答案

其实这个现象中有两个点须要说明:get

1.关于17行为何会打印出true?虚拟机

这个是虚拟机字节码指令invokevirtual的动态查找过程的表现。编译

1三、23字节的指令的参数均为同一引用Lorg/hanyan/test/testClass/SuperT3,这里我以前理解的不深入,其实这里的引用是“符号引用”,指SuperT3类常量池中的某个CONTANT_Methodref_info类型的“符号引用”。但虚拟机执行引擎在运行期执行这个字节码指令时,首先会查找这条指令的接收者(调用者)的实际类型,而后再肯定真正的“直接引用”指向哪里。这个解析操做实现了方法的动态分派,也就是咱们常说的“方法重写”。(具体“符号引用”解析为“直接引用”的解释请参考java的动态解析)。因此1三、23的字节码指令的接收者实际是SubT3,即返回true。class

那么就会引出第二个关注点,代码的15行为何是“Jack”?

2.代码的15行为何是“Jack”?

虚拟机字节码指令getfeild,与invokevirtual不一样,不存在动态查找过程。因此,getfeild字节码指令的参数为当前类的常量池的“符号引用”,此时的“符号引用”已在类加载过程当中的“解析”阶段转化为“直接引用”,即表示当前类的变量name的值,因此返回“Jack”。

至此,整个解释完毕。

总结,this关键字也只是在编译好的字节码文件中,方法的第一个参数(方法的接收者)的访问符而已。整个问题的重点应该关注虚拟机如何执行这些字节码指令。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值