Java中的合成类

时间:2008-12-30 04:39:43

标签: java class synthetic

Java中的合成类是什么?为什么要使用它?我该如何使用它?

13 个答案:

答案 0 :(得分:102)

Java能够在运行时创建类。这些类称为Synthetic Classes或Dynamic Proxies。

有关详细信息,请参阅http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html

其他开源库,例如CGLIBASM,也允许您生成合成类,并且比JRE提供的库更强大。

合成类由AOP(面向方面​​编程)库(如Spring AOP和AspectJ)以及ORM库(如Hibernate)使用。

答案 1 :(得分:54)

我找到了谷歌第一个问题的答案:

  

如果一个类可能被标记为合成   它是由编译器生成的   是的,它没有出现在源头   代码。

这只是一个基本的定义,但我在一个论坛帖子中找到它并且没有解释。还在寻找更好的......

答案 2 :(得分:14)

例如,当你有一个switch语句时,java会创建一个以$开头的变量。如果你想看一个这样的例子,请查看其中包含switch语句的类的java反射。当您在类中的任何位置至少有一个switch语句时,您将看到这些变量。

要回答你的问题,我不相信你能够访问(除了反思)合成类。

如果您正在分析一个您不了解的类(通过反射)并且需要知道关于该类的非常具体和低级的事情,您最终可能会使用与合成有关的Java反射方法类。这里唯一的“使用”是获取有关该类的更多信息,以便在您的代码中正确使用它。

(如果你这样做,你可能正在构建一些其他开发人员可以使用的框架。)

否则,如果你没有使用反射,我所知道的合成类没有实际用途。

答案 3 :(得分:13)

合成类/方法/字段:

这些对于VM很重要。看看下面的代码片段:

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() {
    }
  }
}

答案 4 :(得分:8)

根据this discussion,尽管语言规范描述了类的“isSynthetic”属性,但实际上这几乎被实现忽略,而不是用于动态代理或匿名类。合成字段和构造函数用于实现嵌套类(字节代码中没有嵌套类的概念,仅在源代码中)。

我认为合成类的概念已被证明是无用的,即没有人关心一个类是否是合成的。使用字段和方法,它可能只在一个地方使用:确定在IDE类结构视图中显示的内容 - 您希望显示常规方法和字段,而不是用于模拟嵌套类的合成方法和字段。 OTOH,你想要匿名课程出现在那里。

答案 5 :(得分:7)

它们是由JVM在运行时创建的,当它们调用内部类的私有成员以进行调试时

JVM在运行时为执行目的而创建的方法,字段和类称为Synthetic

http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html

http://javapapers.com/core-java/java-synthetic-class-method-field/

答案 6 :(得分:3)

EasyMock也使用Synthetic Classes或Dynamic Proxies在运行时创建接口或抽象类的实现。

http://www.easymock.org/

答案 7 :(得分:2)

当Java编译器编译某些构造(如内部类)时,它会创建 合成构造 ;这些是类,方法,字段和其他在源代码中没有相应构造的构造。
用途: 合成构造使Java编译器能够在不更改JVM的情况下实现新的Java语言功能。但是,合成构造在不同的Java编译器实现中可能会有所不同,这意味着.class文件也可能因不同的实现而异。
参考:docs.oracle.com

答案 8 :(得分:2)

正如各种答案已经指出的那样,允许编译器生成各种结构(包括类),这些结构不直接对应于源代码中的某些内容。这些必须标记为合成:

13.1. The Form of a Binary

  

类或接口的二进制表示形式还必须包含以下所有内容:
  [...]
  11.如果Java编译器发出的构造与源代码中显式或隐式声明的构造不对应,则必须将其标记为合成,除非发出的构造是类初始化方法(JVMS§2.9)。
  [...]

@Holger在对另一个问题的评论中指出,此类构造的相关示例是表示方法引用和lambda的Class对象:

System.out.println(((Runnable) System.out::println).getClass().isSynthetic());
System.out.println(((Runnable) () -> {}).getClass().isSynthetic());

输出:

true
true

虽然没有明确提及,但它来自 15.27.4. Run-Time Evaluation of Lambda Expressions

  

lambda表达式的值是对具有以下属性的类的实例的引用:[...]

以及方法引用(15.13.3. Run-Time Evaluation of Method References)几乎相同的措词。

由于此类未在源代码中的任何地方明确提及,因此必须是合成的。

答案 9 :(得分:1)

如果我做对了,合成类就是动态生成的类,而不必给它一个明确的名字。例如:

//...
Thread myThread = new Thread() {
         public void run() {
           // do something ...
         }
       };
myThread.start();
//...

这将创建一个Thread的合成子类并覆盖其run()方法,然后实例化它并启动它。

答案 10 :(得分:0)

合成构造是在源代码中没有相应构造的类,方法,字段等。合成构造使Java编译器能够在不更改JVM的情况下实现新的Java语言功能。但是,合成结构可能因不同的Java编译器实现而异,这意味着.class文件也可能因不同的实现而异。

答案 11 :(得分:0)

合成类不会出现在您的代码中:它由编译器组成。 例如。由java编译器构成的桥接方法通常是合成的。

public class Pair<T> {
    private T first;
    private T second;
    public void setSecond(T newValue) {
        second = newValue;
    }
}


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

这是由编译器组成的;它不会出现在您的代码中。

答案 12 :(得分:0)

  

什么是Java中的综合类?

synthetic类是Java Compiler生成的.class文件,它在源代码中不存在。

synthetic类的用法示例:匿名内部类

  

为什么要使用它?

这是Java编译器逻辑内部的一种机制,用于生成.class文件

  

我如何使用它?

否,开发人员不会直接使用它。

Java编译器使用synthetic生成.class文件,然后JVM读取.class文件以执行程序逻辑。

更多详细信息

  • article详细解释了synthetic
  • link列出了JDK中的所有synthetic类出口