Synthetic 表示合成,在 Java 中,这个概念非常生僻,表示一个合成类,合成方法
合成方法
在 SyntheticTest 中提供了一个内部类 SyntheticTestInner,这个内部类提供了一个私有字段 name,按道理说,从外部类 new 了一个内部类,按道理说 Java 规定访问其他类的私有变量,需要提供 getter 方法,但是 name 并没有提供,那么是怎么做到的呢?
其实 Java 给内部类开了一个绿灯,在访问内部类私有变量的时候,JVM 在编译的时候,提供了一个 access$XXX 的方法,这个方法相当于给 name 提供了一个 setter 方法,这个 access$XXX 方法,并不是我们加的,而是 JVM 加的,这个就是合成方法
public class SyntheticTest {public void showName() {SyntheticTestInner syntheticTestInner = new SyntheticTestInner();System.out.println(syntheticTestInner.name);}class SyntheticTestInner {private String name = "SyntheticTestInner";}public static void main(String[] args) {new SyntheticTest().showName(); // SyntheticTestInnerfor (Method declaredMethod : SyntheticTestInner.class.getDeclaredMethods()) {System.out.println(declaredMethod.getName() + ", Synthetic = " + declaredMethod.isSynthetic());}}}// access$100, Synthetic = true
我们在从编译的角度来看
// javap SyntheticTest$SyntheticTestInner.classclass org.wesoft.spring.aop.SyntheticTest$SyntheticTestInner {final org.wesoft.spring.aop.SyntheticTest this$0;static java.lang.String access$100(org.wesoft.spring.aop.SyntheticTest$SyntheticTestInner);}
合成类
我们给内部类加上一个私有无参构造方法,我们依然从外部类定了一个方法,这个方法顺利的 new 出来内部类,这个又和 Java 的定义不符,不是说好了,私有化无参构造方法,就不能以无参的方式 new 对象了么?
没错,Java 依然给内部类开了绿灯,当内部是私有化自己的无参构造方法时,JVM 会给其从新创建一个新的公共的含参构造方法,其参数为自己生产的一个类 SyntheticTest$1.class,
public class SyntheticTest {public void newInnerClass() {SyntheticTestInner syntheticTestInner = new SyntheticTestInner();System.out.println(syntheticTestInner.name);}class SyntheticTestInner {private String name = "SyntheticTestInner";private SyntheticTestInner() {}}public static void main(String[] args) {for (Constructor<?> declaredConstructor : SyntheticTestInner.class.getDeclaredConstructors()) {System.out.println(declaredConstructor.getName() + ", Synthetic = " + declaredConstructor.isSynthetic());}}}// SyntheticTest$SyntheticTestInner(SyntheticTest), Synthetic = false// SyntheticTest$SyntheticTestInner(SyntheticTest, SyntheticTest$1), Synthetic = true
所以,我们 new 内部类的时候,其实使用的是第二个构造方法,同时偷偷的传了一个合成类 SyntheticTest$1,来达到 new SyntheticTestInner() 的目的
我们也从编译的角度来看
class org.wesoft.spring.aop.SyntheticTest$SyntheticTestInner {final org.wesoft.spring.aop.SyntheticTest this$0;org.wesoft.spring.aop.SyntheticTest$SyntheticTestInner(org.wesoft.spring.aop.SyntheticTest, org.wesoft.spring.aop.SyntheticTest$1);static java.lang.String access$100(org.wesoft.spring.aop.SyntheticTest$SyntheticTestInner);}class org.wesoft.spring.aop.SyntheticTest$1 {}
