最终引用的优化如何在java中工作?

bsi*_*nau 8 java optimization compilation

我一直试图弄清楚Java优化的所有内容,并发现了一些有趣的东西.

第一种情况:原始类型编译时优化

public class Clazz {
    public static void main(String args[]) {
        final int i = 300;
        new Clazz() {
            void foo() {
                System.out.println(i);
            }
        }.foo();
    }
}
Run Code Online (Sandbox Code Playgroud)

编译后(我jd-gui-0.3.5.windows用来反编译二进制文件)看起来像:

public class Clazz {
    public static void main(String[] args) {
        int i = 300;
        new Clazz() {
            void foo() {
                System.out.println(300);
            }
        }.foo();
    }
}
Run Code Online (Sandbox Code Playgroud)

不出所料,不是吗?i在编译之后被替换为它的值(内联优化).因此,我希望在用它的包装器替换原始类型之后看到类似的东西,但......

第二种情况:非原始类型的编译时优化

public class Clazz {
    public static void main(String args[]) {
        final Integer i = 300; // replaced int with Integer
        new Clazz() {
            void foo() {
                System.out.println(i);
            }
        }.foo();
    }
}
Run Code Online (Sandbox Code Playgroud)

编译后:

public class Clazz {
    public static void main(String[] args) {
        Integer i = Integer.valueOf(300);
        new Clazz() {
            void foo() {
                System.out.println(Clazz.this);
            }
        }.foo();
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:

什么是Clazz.this在这种情况下?我知道,它是封闭实例的参考Clazz,但在这种情况下不应该有效!我需要打印i,但编译器建议我打印Clazz.this而不是它,它的工作原理!问题是什么?jd-gui反编译是否错误或者我是否遗漏了有关Java编译和优化的内容?

UPD:

内容Class$1:

class Clazz$1 extends Clazz {
    Clazz$1(Integer paramInteger) {}

    void foo() {
        System.out.println(this.val$i);
    }
}
Run Code Online (Sandbox Code Playgroud)

NPE*_*NPE 8

jd-gui反编译是否错误或者我是否遗漏了有关Java编译和优化的内容?

jd-gui 正在反编译错误的代码.

在我的JVM上,匿名类的反汇编代码如下所示:

class Clazz$1 extends Clazz {
  Clazz$1(java.lang.Integer);
    Code:
       0: aload_0       
       1: aload_1       
       2: putfield      #10                 // Field val$i:Ljava/lang/Integer;
       5: aload_0       
       6: invokespecial #12                 // Method Clazz."<init>":()V
       9: return        

  void foo();
    Code:
       0: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;
       3: aload_0       
       4: getfield      #10                 // Field val$i:Ljava/lang/Integer;
       7: invokevirtual #26                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      10: return        
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,i存储在匿名类中的副本,在字段中称为val$i(名称是特定于实现的).

您的反编译器似乎错误地呈现为此字段Clazz.this.