Attr的visitNewClass()方法解读
在visitNewClass()方法中有如下注释:
We are seeing an anonymous class instance creation.
In this case, the class instance creation expression
E.new <typeargs1>C<typargs2>(args) { ... }
is represented internally as
E . new <typeargs1>C<typargs2>(args) ( class <empty-name> { ... } ) .
This expression is then *transformed* as follows:
(1) add a STATIC flag to the class definition if the current environment is static
(2) add an extends or implements clause
(3) add a constructor.
For instance, if C is a class, and ET is the type of E, the expression
E.new <typeargs1>C<typargs2>(args) { ... }
is translated to (where X is a fresh name and typarams is the
parameter list of the super constructor):
new <typeargs1>X(<*nullchk*>E, args)
where
X extends C<typargs2> { <typarams> X(ET e, args) { e.<typeargs1>super(args) } ... }
举个例子,如下:
class E{ class C<T1>{ // C的构造函数 public <T2> C(){ } public void t(){ E e = new E(); e.new <String>C<Integer>(){}; } } }
按如上的描述,应该被改写为:
class E{ class C<T1>{ // C的构造函数 public <T2> C(){ } public void t(){ E e = new E(); new <String>X(e); // 更改为了这样的形式 } } } class X extends E.C<Integer>{ <T2> X(E e){ e.<T2>super(); } }
传入visitNewClass()方法的tree参数如下截图。
通过调用visitNewClass()方法后,e.new <String>C<Integer>(){}方法被改写为:
new <String>C<Integer>(e<*nullchk*>){ <T2 extends java.lang.Object>(com.test19.E x0) { x0.<T2>super(); } }
编译后生成3个Class文件,如下:
(1)E.class,通过调用Attr类的visitNewClass()方法后,e.new <String>C<Integer>(){}方法被改写为:
class E { E() { super(); } class C<T1> { public <T2>C() { super(); } public void t() { E e = new E(); new <String>C<Integer>(e<*nullchk*>){ <T2 extends .java.lang.Object>(.com.test19.E x0) { x0.<T2>super(); } }; } } }
最终的字节码如下:
class com.test19.E SourceFile: "Test07.java" InnerClasses: #5= #4 of #2; //C=class com/test19/E$C of class com/test19/E minor version: 0 major version: 51 flags: ACC_SUPER Constant pool: #1 = Methodref #3.#16 // java/lang/Object."<init>":()V #2 = Class #17 // com/test19/E #3 = Class #18 // java/lang/Object #4 = Class #19 // com/test19/E$C #5 = Utf8 C #6 = Utf8 InnerClasses #7 = Utf8 <init> #8 = Utf8 ()V #9 = Utf8 Code #10 = Utf8 LineNumberTable #11 = Utf8 LocalVariableTable #12 = Utf8 this #13 = Utf8 Lcom/test19/E; #14 = Utf8 SourceFile #15 = Utf8 Test07.java #16 = NameAndType #7:#8 // "<init>":()V #17 = Utf8 com/test19/E #18 = Utf8 java/lang/Object #19 = Utf8 com/test19/E$C { com.test19.E(); 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 4: 0 line 5: 4 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/test19/E; }
(2)E$C通过调用desugar类后如下:
class E$C { /*synthetic*/ final E this$0; public E$C(/*synthetic*/ final E this$0) { this.this$0 = this$0; super(); } public void t() { E e = new E(); new <String>E$C$1(this, e<*nullchk*>); } }
最终的字节码如下:
class com.test19.E$C<T1 extends java.lang.Object> extends java.lang.Object Signature: #29 // <T1:Ljava/lang/Object;>Ljava/lang/Object; SourceFile: "Test07.java" InnerClasses: #10= #8 of #3; //C=class com/test19/E$C of class com/test19/E #5; //class com/test19/E$C$1 minor version: 0 major version: 51 flags: ACC_SUPER Constant pool: #1 = Fieldref #8.#32 // com/test19/E$C.this$0:Lcom/test19/E; #2 = Methodref #9.#33 // java/lang/Object."<init>":()V #3 = Class #34 // com/test19/E #4 = Methodref #3.#33 // com/test19/E."<init>":()V #5 = Class #35 // com/test19/E$C$1 #6 = Methodref #9.#36 // java/lang/Object.getClass:()Ljava/lang/Class; #7 = Methodref #5.#37 // com/test19/E$C$1."<init>":(Lcom/test19/E$C;Lcom/test19/E;)V #8 = Class #38 // com/test19/E$C #9 = Class #39 // java/lang/Object #10 = Utf8 C #11 = Utf8 InnerClasses #12 = Utf8 #13 = Utf8 this$0 #14 = Utf8 Lcom/test19/E; #15 = Utf8 <init> #16 = Utf8 (Lcom/test19/E;)V #17 = Utf8 Code #18 = Utf8 LineNumberTable #19 = Utf8 LocalVariableTable #20 = Utf8 this #21 = Utf8 Lcom/test19/E$C; #22 = Utf8 LocalVariableTypeTable #23 = Utf8 Lcom/test19/E$C<TT1;>; #24 = Utf8 Signature #25 = Utf8 <T2:Ljava/lang/Object;>()V #26 = Utf8 t #27 = Utf8 ()V #28 = Utf8 e #29 = Utf8 <T1:Ljava/lang/Object;>Ljava/lang/Object; #30 = Utf8 SourceFile #31 = Utf8 Test07.java #32 = NameAndType #13:#14 // this$0:Lcom/test19/E; #33 = NameAndType #15:#27 // "<init>":()V #34 = Utf8 com/test19/E #35 = Utf8 com/test19/E$C$1 #36 = NameAndType #40:#41 // getClass:()Ljava/lang/Class; #37 = NameAndType #15:#42 // "<init>":(Lcom/test19/E$C;Lcom/test19/E;)V #38 = Utf8 com/test19/E$C #39 = Utf8 java/lang/Object #40 = Utf8 getClass #41 = Utf8 ()Ljava/lang/Class; #42 = Utf8 (Lcom/test19/E$C;Lcom/test19/E;)V { final com.test19.E this$0; flags: ACC_FINAL, ACC_SYNTHETIC public <T2 extends java/lang/Object> com.test19.E$C(); flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: aload_1 2: putfield #1 // Field this$0:Lcom/test19/E; 5: aload_0 6: invokespecial #2 // Method java/lang/Object."<init>":()V 9: return LineNumberTable: line 7: 0 LocalVariableTable: Start Length Slot Name Signature 0 10 0 this Lcom/test19/E$C; LocalVariableTypeTable: Start Length Slot Name Signature 0 10 0 this Lcom/test19/E$C<TT1;>; Signature: #25 // <T2:Ljava/lang/Object;>()V public void t(); flags: ACC_PUBLIC Code: stack=5, locals=2, args_size=1 0: new #3 // class com/test19/E 3: dup 4: invokespecial #4 // Method com/test19/E."<init>":()V 7: astore_1 8: new #5 // class com/test19/E$C$1 11: dup 12: aload_0 13: aload_1 14: dup 15: invokevirtual #6 // Method java/lang/Object.getClass:()Ljava/lang/Class; 18: pop 19: invokespecial #7 // Method com/test19/E$C$1."<init>":(Lcom/test19/E$C;Lcom/test19/E;)V 22: pop 23: return LineNumberTable: line 10: 0 line 11: 8 line 12: 23 LocalVariableTable: Start Length Slot Name Signature 0 24 0 this Lcom/test19/E$C; 8 16 1 e Lcom/test19/E; LocalVariableTypeTable: Start Length Slot Name Signature 0 24 0 this Lcom/test19/E$C<TT1;>; }
(3)E$C$1通过调用desugar类后代码如下:
class E$C$1 extends com.test19.E$C { /*synthetic*/ final E$C this$1; E$C$1(/*synthetic*/ final E$C this$1, com.test19.E x0) { this.this$1 = this$1; <T2>super(x0<*nullchk*>); } }
最终编译后的字节码如下:
class com.test19.E$C$1 extends com.test19.E$C<java.lang.Integer> Signature: #23 // Lcom/test19/E$C<Ljava/lang/Integer;>; SourceFile: "Test07.java" EnclosingMethod: #5.#27 // com.test19.E$C.t InnerClasses: #7= #5 of #33; //C=class com/test19/E$C of class com/test19/E #4; //class com/test19/E$C$1 minor version: 0 major version: 51 flags: ACC_SUPER Constant pool: #1 = Fieldref #4.#28 // com/test19/E$C$1.this$1:Lcom/test19/E$C; #2 = Methodref #29.#30 // java/lang/Object.getClass:()Ljava/lang/Class; #3 = Methodref #5.#31 // com/test19/E$C."<init>":(Lcom/test19/E;)V #4 = Class #32 // com/test19/E$C$1 #5 = Class #34 // com/test19/E$C #6 = Utf8 this$1 #7 = Utf8 C #8 = Utf8 InnerClasses #9 = Utf8 Lcom/test19/E$C; #10 = Utf8 <init> #11 = Utf8 (Lcom/test19/E$C;Lcom/test19/E;)V #12 = Utf8 Code #13 = Utf8 LineNumberTable #14 = Utf8 LocalVariableTable #15 = Utf8 this #16 = Utf8 #17 = Utf8 Lcom/test19/E$C$1; #18 = Utf8 x0 #19 = Utf8 Lcom/test19/E; #20 = Utf8 LocalVariableTypeTable #21 = Utf8 Lcom/test19/E$C.1; #22 = Utf8 Signature #23 = Utf8 Lcom/test19/E$C<Ljava/lang/Integer;>; #24 = Utf8 SourceFile #25 = Utf8 Test07.java #26 = Utf8 EnclosingMethod #27 = NameAndType #35:#36 // t:()V #28 = NameAndType #6:#9 // this$1:Lcom/test19/E$C; #29 = Class #37 // java/lang/Object #30 = NameAndType #38:#39 // getClass:()Ljava/lang/Class; #31 = NameAndType #10:#40 // "<init>":(Lcom/test19/E;)V #32 = Utf8 com/test19/E$C$1 #33 = Class #41 // com/test19/E #34 = Utf8 com/test19/E$C #35 = Utf8 t #36 = Utf8 ()V #37 = Utf8 java/lang/Object #38 = Utf8 getClass #39 = Utf8 ()Ljava/lang/Class; #40 = Utf8 (Lcom/test19/E;)V #41 = Utf8 com/test19/E { final com.test19.E$C this$1; flags: ACC_FINAL, ACC_SYNTHETIC com.test19.E$C$1(com.test19.E$C, com.test19.E); flags: Code: stack=3, locals=3, args_size=3 0: aload_0 1: aload_1 2: putfield #1 // Field this$1:Lcom/test19/E$C; 5: aload_0 6: aload_2 7: dup 8: invokevirtual #2 // Method java/lang/Object.getClass:()Ljava/lang/Class; 11: pop 12: invokespecial #3 // Method com/test19/E$C."<init>":(Lcom/test19/E;)V 15: return LineNumberTable: line 11: 0 LocalVariableTable: Start Length Slot Name Signature 0 16 0 this Lcom/test19/E$C$1; 0 16 2 x0 Lcom/test19/E; LocalVariableTypeTable: Start Length Slot Name Signature 0 16 0 this Lcom/test19/E$C.1; }
Attr的visitNewClass()方法解读的更多相关文章
- jQuery操纵DOM元素属性 attr()和removeAtrr()方法使用详解
jQuery操纵DOM元素属性 attr()和removeAtrr()方法使用详解 jQuery中操纵元素属性的方法: attr(): 读或者写匹配元素的属性值. removeAttr(): 从匹配的 ...
- jquery中dom元素的attr和prop方法的理解
一.背景 在编写使用高版本[ jQuery 1.6 开始新增了一个方法 prop()]的jquery插件进行编写js代码的时候,经常不知道dom元素的attr和prop方法到底有什么区别?各自有什么应 ...
- input是否checked与使用jquery的attr或prop方法无关
最近在项目中有这样一个需求,用户在下单时可以选择优惠券,也可取消选择,并且可以多次选择,取消. 这是一个典型的input标签checked功能,博主使用radio元素实现此需求,但是优惠券只能选中,不 ...
- Connection 对象简介 方法解读 JDBC简介(四)
通过驱动管理器DriverManager的getConnection方法,可以创建到指定URL的连接 Connection conn = DriverManager.getConnection ...
- jQuery .attr()和.removeAttr()方法操作元素属性示例
今天主要和大家一起分享一下如何使用jQuery的.attr()和.removeAttr()方法读取,添加,修改,删除元素的属性.大家在平时的Web页面制作中都有碰到如何动态的获取元素的属性和属性值,或 ...
- jQuery中attr和prop方法的区别
jQuery中attr和prop方法的区别。 http://my.oschina.net/bosscheng/blog/125833 http://www.javascript100.com/?p=8 ...
- $().attr()的使用方法 && $().html()与$().text()的差别
<1>$().attr()的使用方法 </pre><pre class="html" name="code"><htm ...
- Java安全之原生readObject方法解读
Java安全之原生readObject方法解读 0x00 前言 在上篇文章分析shiro中,遇到了Shiro重写了ObjectInputStream的resolveClass导致的一些基于Invoke ...
- jQuery 中 attr() 和 prop() 方法的区别
前几天,有人给 Multiple Select 插件 提了问题: setSelects doesn't work in Firefox when using jquery 1.9.0 一直都在用 jQ ...
随机推荐
- dom4j 通过 org.dom4j.DocumentFactory 设置命名空间来支持 带namespace 的 xpath
测试文件 test.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:/ ...
- redis-server进程CPU百分百问题
结论:待确认是否为redis的BUG,原因是进程实际占用的内存远小于配置的最大内存,所以不会是内存不够需要淘汰.CPU百分百redis-server进程集群状态:slave临时解决办法:使用gdb将d ...
- Different timers in .net
Multi-threads timers: System.Threading.Timer and System.Timers.Timer (.net framework): App will hand ...
- Qt_HelloWrold
新建工程 -> 选择Qt Gui 应用 然后点击选择 在弹出的对话框中填写名称,创建路径等信息: 点击下一步,选择该工程的编译器. 点击下一步,可以选择生成的主窗口文件.不过这里我们仅仅用简单的 ...
- (多线程dp)Matrix (hdu 2686)
http://acm.hdu.edu.cn/showproblem.php?pid=2686 Problem Description Yifenfei very like play a num ...
- 服务化实战之 dubbo、dubbox、motan、thrift、grpc等RPC框架比较及选型
转自: http://blog.csdn.net/liubenlong007/article/details/54692241 概述 前段时间项目要做服务化,所以我比较了现在流行的几大RPC框架的优缺 ...
- 如何防止ElasticSearch集群出现脑裂现象
什么是“脑裂”现象? 由于某些节点的失效,部分节点的网络连接会断开,并形成一个与原集群一样名字的集群,这种情况称为集群脑裂(split-brain)现象.这个问题非常危险,因为两个新形成的集群会同时索 ...
- CF每日一题系列 —— 415A
http://codeforces.com/problemset/page/7?order=BY_SOLVED_DESC 从5000以内选的,emmm还是比较水的哈 时间还是有的,所以万事万物贵在坚持 ...
- python 读取hive数据
话不多说,直接上代码 from pyhive import hivedef pyhive(hql): conn = hive.Connection(host='HiveServer2 host', p ...
- Windows核心编程:第5章 作业
Github https://github.com/gongluck/Windows-Core-Program.git //第5章 作业.cpp: 定义应用程序的入口点. // #include &q ...