synthetic 是什么
由
jvm
编译器生成的:字段、方法、构造函数,会标注为synthetic。
为什么jvm
编译器会生成一些字段、方法、构造函数?
举个例子:一个内部类演示
public class SyntheticDemo {
private String hello() {
return "hello World";
}
class SyntheticDemoInner {
public void printName() {
System.out.println(hello());
}
}
}
通过 javac
编译后,内部类
会生成一个单独的类文件。
若是按照Java语法规范内部类直接调用 hello
方法是会直接报错。
通过反编译查看类文件:反编译在线地址
public class SyntheticDemo {
private String hello() {
return "hello World";
}
// $FF: synthetic method
static String access$000(SyntheticDemo var0) {
return var0.hello();
}
}
import com.liuqi.synthetic.SyntheticDemo;
class SyntheticDemo$SyntheticDemoInner {
// $FF: synthetic field
final SyntheticDemo this$0;
SyntheticDemo$SyntheticDemoInner(SyntheticDemo var1) {
this.this$0 = var1;
}
public void printName() {
System.out.println(SyntheticDemo.access$000(this.this$0));
}
}
SyntheticDemo
类中生成了一个access$000
方法去调用hello
方法。
SyntheticDemo$SyntheticDemoInner
内部类中添加了一个字段this$0
,指向SyntheticDemo
,而在调用SyntheticDemo.hello
方法时被修改成SyntheticDemo.access$000(this.this$0)
SyntheticDemo
类中为什么生成了access$000
方法?
在java语法规范中,外部类不能直接调用本类
private
修饰符的字段、方法、构造函数。
内部类
构造函数中为什么有SyntheticDemo
实例入参?
需要持有该实例才能调用此类的方法。
这也就是为什么内部类不能在外部进行实例化:因为在内部类构造函数中,需要传递SyntheticDemo
实例入参。
如何查看是否是synthetic
通过:Modifier.isSynthetic(int modifiers);
,或者Field
,Method
,Constructor
的isSynthetic
方法
synthetic 作用
让内部类编译完后,符合Java语法规范。
注意:
在JDK11开始的
NBAC
机制(Nested Based Access Controll)消除了,内部类的private
修饰符访问权限控制,就不会在生成一些default
权限的方法去访问private
的方法。