我正在查看从Java字节码获得的一些反汇编代码。我看到一些声明如下:
.method static synthetic access$0()Lcom/package/Sample;
我无法弄清synthetic
或access$0
的含义。有人可以帮我理解这部分吗?
答案 0 :(得分:30)
在java语言中,内部类可以访问其封闭类的私有成员。但是,在Java字节码中,内部类的概念不存在,并且私有成员不可访问。要解决此问题,编译器会在外部类中创建合成访问器方法。我相信这就是你在这里看到的。 access$0
只是方法的名称。我不确定synthetic
是做什么的。它可能只是隐藏其他编译器的方法以确保封装。
答案 1 :(得分:26)
编译器创建的字段,用于将本地内部类链接到块的局部变量或引用类型参数。
另请参阅The JavaTM Virtual Machine Specification (§4.7.6)
或Synthetic Class in Java。
答案 2 :(得分:4)
assert
声明JDK 1.8案例研究
assert
语句是在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 field is synthetic.
static final boolean $assertionsDisabled =
!Assert.class.desiredAssertionStatus();
public static void main(String[] args) {
if (!$assertionsDisabled) {
if (System.currentTimeMillis() != 0L) {
throw new AssertionError();
}
}
}
}
可以通过以下方式验证:
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;
}
}
"唯一阻止"这是在标识符上不使用美元的命名约定。另见:When should I use the dollar symbol ($) in a variable name?
加成:
static final int $assertionsDisabled = 0;
可行,因为与Java不同,字节码允许多个具有相同名称但不同类型的字段:Variables having same name but different type