Java中的合成类
Java中的合成类是什么? 为什么要使用它? 我怎样才能使用它?
例如,当你有一个switch语句时,java创build一个以$开头的variables。 如果你想看一个这样的例子,可以窥探一个类中有一个switch语句的javareflection。 如果class级中至less有一个switch语句,您将看到这些variables。
要回答你的问题,我不相信你能够访问(反思)合成类。
如果你正在分析一个你不了解的类(通过reflection),并且需要知道关于这个类的非常具体和低级的事情,那么你最终可能会使用与合成类有关的Javareflection方法。 这里唯一的“使用”是获得更多关于类的信息,以便在代码中正确使用它。
(如果你这样做,你可能会build立一个其他开发者可以使用的框架。)
否则,如果你没有使用reflection,我不知道合成类的实际用途。
Java有能力在运行时创build类。 这些类被称为合成类或dynamic代理。
有关更多信息,请参阅http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html 。
其他开源库(如CGLIB和ASM)也允许您生成合成类,并且比JRE提供的库更强大。
AOP(面向方面编程)库(如Spring AOP和AspectJ)以及诸如Hibernate的ORM库都使用合成类。
那么我find了谷歌第一个问题的答案:
如果一个类是由编译器生成的,那么它可能被标记为合成的,也就是说,它不会出现在源代码中。
这只是一个基本的定义,但我发现它在一个论坛主题,没有任何解释。 还在寻找一个更好的…
合成类/方法/领域:
这些对于虚拟机来说很重要。 看看下面的代码片段:
class MyOuter { private MyInner inner; void createInner() { // The Compiler has to create a synthetic method // to construct a new MyInner because the constructor // is private. // --> synthetic "constructor" method inner = new MyInner(); // The Compiler has to create a synthetic method // to doSomething on MyInner object because this // method is private. // --> synthetic "doSomething" method inner.doSomething(); } private class MyInner { // the inner class holds a syntetic ref_pointer to // the outer "parent" class // --> synthetic field private MyInner() { } private void doSomething() { } } }
根据这个讨论 ,尽pipe语言规范描述了一个类的“isSynthetic”特性,但是这个特性在实现中几乎被忽略,并且不用于dynamic代理或者匿名类。 合成域和构造函数用于实现嵌套类(在字节码中没有嵌套类的概念,只有在源代码中)。
我认为合成类的概念简单地certificate是没有用的,即没有人关心一个类是否是合成的。 使用字段和方法,可能只是在一个地方使用它:确定在IDE类结构视图中显示的内容 – 您希望在其中显示常规方法和字段,而不是用于模拟嵌套类的合成方法和字段。 OTOH,你想要匿名的课程在那里出现。
它们是在运行时由JVM创build的,当它们调用内部类的私有成员进行debugging时
JVM在运行期间为实现目的而创build的方法,字段,类称为Synthetic
http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html
http://javapapers.com/core-java/java-synthetic-class-method-field/
EasyMock还使用Synthetic Classes或Dynamic Proxies在运行时创build接口或抽象类的实现。
如果我理解正确的话,那么一个合成类就是一个dynamic生成的类,而不必给它一个明确的名字。 例如:
//... Thread myThread = new Thread() { public void run() { // do something ... } }; myThread.start(); //...
这将创build一个Thread的合成子类并重写它的run()方法,然后实例化并启动它。
当Java编译器编译某些结构(如内部类)时,会创build合成结构 ; 这些是在源代码中没有相应构造的类,方法,字段和其他构造。
用途:合成结构使Java编译器能够在不改变JVM的情况下实现新的Java语言特性。 但是,合成结构在不同的Java编译器实现中可能会有所不同,这意味着.class文件在不同的实现中也会有所不同。
参考: docs.oracle.com
合成结构是源代码中没有相应结构的类,方法,字段等。 合成结构使Java编译器能够在不改变JVM的情况下实现新的Java语言特性。 但是,合成结构在不同的Java编译器实现中可能会有所不同,这意味着.class文件在不同的实现中也会有所不同。
我在一个反汇编的java 5+项目中看到了一个合成类。 原来,这是一个编译器hack实现开关枚举。
合成类不会出现在您的代码中,而是由编译器组成。 例如,由java编译器构成的Bridge方法通常是合成的。
public class Pair<T> { private T first; private T second; public void setSecond(T newValue) { second = newValue; }// Of seSecond }// Of class Pair<T> public class DateInterval extends Pair<String> { public void setSecond(String second) { System.out.println("OK sub"); } public static void main(String[] args) throws NoSuchFieldException, SecurityException { DateInterval interval = new DateInterval(); Pair pair = interval; pair.setSecond("string1"); } }
使用javap -verbose DateInterval
指令,你可以看到一个桥接方法
public void setSecond(java.lang.Object); flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
它由编译器组成,但是不会出现在你的代码中。