Attr的visitNewClass()方法解读

 

 

在visitNewClass()方法中有如下注释:

We are seeing an anonymous class instance creation.
In this case, the class instance creation expression

E.new C(args) { ... }

is represented internally as  

E . new C(args) ( class  { ... } )  .

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 C(args) { ... }

is translated to (where X is a fresh name and typarams is the
parameter list of the super constructor):

new X(<*nullchk*>E, args)

where  

X extends C {
       X(ET e, args) {
        e.super(args)
      }
      ...
}

 

举个例子,如下: 

class E{
	class C{
		// C的构造函数
		public  C(){ }
		
		public void t(){
			E e = new E();
			e.new C(){};
		}
	}
}

 

按如上的描述,应该被改写为:

class E{
    class C{
        // C的构造函数
        public  C(){ }
         
        public void t(){
            E e = new E();
            new X(e); // 更改为了这样的形式
        }
    }
}
class X extends E.C{
	 X(E e){
		e.super();
	}
}  

 

传入visitNewClass()方法的tree参数如下截图。

Attr的visitNewClass()方法解读_第1张图片

 

 

通过调用visitNewClass()方法后,e.new C(){}方法被改写为:

new C(e<*nullchk*>){
    (com.test19.E x0) {
           x0.super();
     }
}

编译后生成3个Class文件,如下:

(1)E.class,通过调用Attr类的visitNewClass()方法后,e.new C(){}方法被改写为: 

class E {
    
    E() {
        super();
    }
    
    class C {
        
        public C() {
            super();
        }
        
        public void t() {
            E e = new E();
            new C(e<*nullchk*>){                
                (.com.test19.E x0) {
                    x0.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."":()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               
   #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          //  "":()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."":()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 E$C$1(this, e<*nullchk*>);
    }
}

最终的字节码如下:

class com.test19.E$C extends java.lang.Object
  Signature: #29                          // 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."":()V
   #3 = Class              #34            //  com/test19/E
   #4 = Methodref          #3.#33         //  com/test19/E."":()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."":(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               
  #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;
  #24 = Utf8               Signature
  #25 = Utf8               ()V
  #26 = Utf8               t
  #27 = Utf8               ()V
  #28 = Utf8               e
  #29 = Utf8               Ljava/lang/Object;
  #30 = Utf8               SourceFile
  #31 = Utf8               Test07.java
  #32 = NameAndType        #13:#14        //  this$0:Lcom/test19/E;
  #33 = NameAndType        #15:#27        //  "":()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        //  "":(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  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."":()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;
    Signature: #25                     // ()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."":()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."":(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;
}

  

  

 

(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;
        super(x0<*nullchk*>);
    }
}

 

最终编译后的字节码如下:

class com.test19.E$C$1 extends com.test19.E$C
  Signature: #23                          // Lcom/test19/E$C;
  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."":(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               
  #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;
  #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        //  "":(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."":(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()方法解读)