“静态合成”是什么意思?

我正在查看从Java字节码获得的一些反汇编代码。 我看到一些声明如下:

.method static synthetic access$0()Lcom/package/Sample; 

我无法弄清楚syntheticaccess$0含义。 有人可以帮我理解这部分吗?

合成油田 , (2)

编译器创建的字段,用于将本地内部类链接到块的局部变量或引用类型参数。

另请参阅The JavaTM Virtual Machine Specification (§4.7.6)或Java中的Synthetic Class 。

在java语言中,内部类可以访问其封闭类的私有成员。 但是,在Java字节码中,内部类的概念不存在,并且私有成员不可访问。 要解决此问题,编译器会在外部类中创建合成访问器方法。 我相信这就是你在这里看到的。 access$0只是方法的名称。 我不确定synthetic是什么。 它可能只是隐藏其他编译器的方法以确保封装。

Oracle JDK 1.8.0_45上的断言是一个生成static synthetic字段的示例:

 public class Assert { public static void main(String[] args) { assert System.currentTimeMillis() == 0L; } } 

基本上编译为:

 public class Assert { // This method is synthetic. static final boolean $assertionsDisabled = !Assert.class.desiredAssertionStatus(); public static void main(String[] args) { if (!$assertionsDisabled) { if (System.currentTimeMillis() != 0L) { throw new AssertionError(); } } } } 

这可以通过以下方式validation:

 javac Assert.java javap -c -constants -private -verbose Assert.class 

其中包含:

  static final boolean $assertionsDisabled; descriptor: Z flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC 

生成合成字段,以便Java只需要在加载时调用Assert.class.desiredAssertionStatus()一次,然后将结果缓存在那里。

另请参阅: https : //stackoverflow.com/a/29439538/895245以获取更详细的说明。

请注意,此合成字段可能会与我们可能定义的其他字段生成名称冲突。 例如,以下无法在Oracle JDK 1.8.0_45上编译:

 public class Assert { static final boolean $assertionsDisabled = false; public static void main(String[] args) { assert System.currentTimeMillis() == 0L; } } 

“阻止”唯一的事情就是不在标识符上使用美元的命名约定。 另请参阅: 何时应在变量名中使用美元符号($)?

奖金:

 static final int $assertionsDisabled = 0; 

可以工作,因为与Java不同,字节码允许多个具有相同名称但不同类型的字段: 具有相同名称但不同类型的变量