Clase sintética en Java

143

¿Qué es una clase sintética en Java? ¿Por qué debería ser usado? ¿Como puedo usar lo?

y feliz
fuente
1
Todas las respuestas "no en su código" están desactualizadas con Java 8, ya que las lambdas pueden implementarse como clases sintéticas (no anónimas).
OrangeDog
Para ser justos, una lambda todavía no es "estrictamente" una clase definida explícitamente en su código. Por lo tanto, "no está en su código" sigue siendo válido. El compilador genera las clases sintéticas para usted sin una definición explícita en su código.
ManoDestra

Respuestas:

15

Por ejemplo, cuando tiene una instrucción switch, java crea una variable que comienza con $. Si desea ver un ejemplo de esto, eche un vistazo al reflejo de Java de una clase que tiene una instrucción switch. Verá estas variables cuando tenga al menos una instrucción de cambio en cualquier lugar de la clase.

Para responder a su pregunta, no creo que pueda acceder (aparte de la reflexión) a las clases sintéticas.

Si está analizando una clase de la que no sabe nada (a través de la reflexión) y necesita saber cosas muy específicas y de bajo nivel sobre esa clase, puede terminar usando métodos de reflexión de Java que tienen que ver con clases sintéticas. El único "uso" aquí es obtener más información sobre la clase para usarla adecuadamente en su código.

(Si está haciendo esto, probablemente esté creando un marco de algún tipo que otros desarrolladores podrían usar).

De lo contrario, si no está utilizando la reflexión, no hay usos prácticos de clases sintéticas que yo sepa.

Milhous
fuente
1
Sí, el código de muestra sería bueno si pudiera proporcionar un ejemplo /
nanofarad
36
Esto no responde la pregunta.
Dawood ibn Kareem
Para el caso del interruptor, no estoy seguro de si esto sucede para cada interruptor, pero he observado esto para el interruptor con enumeraciones; el compilador genera una clase anónima con un solo campo estático que proporciona un mapeo Enum.ordinal () -> 1, 2, 3 ... (entonces una secuencia sin espacios), y luego una instrucción de búsqueda de interruptor ejecuta el interruptor en esta secuencia, no directamente en ordinales.
Radim Vansa
106

Java tiene la capacidad de crear clases en tiempo de ejecución. Estas clases se conocen como clases sintéticas o proxies dinámicos.

Consulte http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html para obtener más información.

Otras bibliotecas de código abierto, como CGLIB y ASM también le permiten generar clases sintéticas, y son más potentes que las bibliotecas proporcionadas con el JRE.

Las bibliotecas de AOP (Programación Orientada a Aspectos) utilizan Spring AOP y AspectJ, así como las bibliotecas de ORM como Hibernate.

Andrew Newdigate
fuente
66
Los proxys dinámicos no son clases sintéticas. Prueba:Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
Miha_x64
3
El javadoc para java.lang.reflect.Member#isSyntheticdice: Devuelve verdadero si este miembro fue introducido por el compilador; devuelve falso de lo contrario.
Guillaume Husta
Creo que el javadoc para java.lang.reflect.Member#isSynthetices irrelevante para la pregunta original. Los miembros son campos, constructores y métodos. La pregunta original era sobre clases sintéticas , no miembros sintéticos. En Java 8, las expresiones lambda dan lugar a clases sintéticas; no estoy seguro de qué otras circunstancias pueden surgir.
P. Jeremy Krieg
54

Bueno, encontré la respuesta a la primera pregunta en google:

Una clase puede marcarse como sintética si es generada por el compilador, es decir, no aparece en el código fuente.

Esta es solo una definición básica, pero la encontré en un hilo del foro y no había explicación. Sigo buscando una mejor ...

y feliz
fuente
15

clases / métodos / campos sintéticos:

Estas cosas son importantes para la VM. Eche un vistazo al siguiente fragmento de código:

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() {
    }
  }
}
Vinay W
fuente
2
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功, no, solo métodos de acceso sintéticos.
Miha_x64
8

De acuerdo con esta discusión , aunque la especificación del lenguaje describe una propiedad "isSynthetic" para las clases, las implementaciones lo ignoran y no se utiliza para servidores proxy dinámicos o clases anónimas. Los campos sintéticos y los constructores se utilizan para implementar clases anidadas (no existe el concepto de clases anidadas en el código de bytes, solo en el código fuente).

Creo que el concepto de clases sintéticas simplemente ha demostrado no ser útil, es decir, a nadie le importa si una clase es sintética. Con los campos y métodos, probablemente se use exactamente en un lugar: para determinar qué mostrar en una vista de estructura de clase IDE: desea que aparezcan los métodos y campos normales allí, pero no los sintéticos utilizados para simular clases anidadas. OTOH, QUIERES que aparezcan clases anónimas allí.

Michael Borgwardt
fuente
@OrangeDog: sí, eso es lo que escribí.
Michael Borgwardt
Esta respuesta parece estar desactualizada ya que java 8 - lambdas y referencias de métodos hacen uso de esta característica. He agregado una respuesta que demuestra eso
Hulk el
7

JVM los crea en tiempo de ejecución cuando invocan a miembros privados de la clase interna para fines de depuración

Los métodos, campos, clase creados por JVM durante el tiempo de ejecución para su propósito de ejecución se denominan sintéticos.

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

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

sathis
fuente
Supongo que te refieres a tiempo de compilación, y no en tiempo de ejecución.
Mostowski Colapso
@sathis, ¿te referías a javac, no a JVM?
Miha_x64
3

EasyMock también utiliza clases sintéticas o proxys dinámicos para crear implementaciones de interfaces o clases abstractas en tiempo de ejecución.

http://www.easymock.org/

usuario2427
fuente
2

Cuando el compilador de Java compila ciertas construcciones, como las clases internas, crea construcciones sintéticas ; Estas son clases, métodos, campos y otras construcciones que no tienen una construcción correspondiente en el código fuente.
Usos: Las construcciones sintéticas permiten que los compiladores de Java implementen nuevas características del lenguaje Java sin cambios en la JVM. Sin embargo, las construcciones sintéticas pueden variar entre diferentes implementaciones del compilador de Java, lo que significa que los archivos .class también pueden variar entre diferentes implementaciones.
referencia: docs.oracle.com

anavaras lamurep
fuente
2

Como varias respuestas ya han señalado, el compilador puede generar varias construcciones (incluidas las clases) que no se corresponden directamente con algo en el código fuente. Estos deben marcarse como sintéticos:

13.1 La forma de un binario

Una representación binaria para una clase o interfaz también debe contener todo lo siguiente:
[...]
11. Una construcción emitida por un compilador Java debe marcarse como sintética si no corresponde a una construcción declarada explícita o implícitamente en el código fuente , a menos que la construcción emitida sea un método de inicialización de clase (JVMS §2.9).
[...]

Como señaló @Holger en un comentario a otra pregunta, ejemplos relevantes para tales construcciones son los objetos de clase que representan referencias de métodos y lambdas:

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

Salida:

true
true

Si bien esto no se menciona explícitamente, se desprende de 15.27.4. Evaluación en tiempo de ejecución de expresiones lambda :

El valor de una expresión lambda es una referencia a una instancia de una clase con las siguientes propiedades: [...]

y la redacción casi idéntica para las referencias de métodos ( 15.13.3. Evaluación en tiempo de ejecución de las referencias de métodos ).

Como esta clase no se menciona explícitamente en ninguna parte del código fuente, tiene que ser sintética.

Casco
fuente
1

Si lo hago bien, se genera una clase sintética sobre la marcha, sin tener que darle un nombre explícito. Por ejemplo:

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

Esto crea una subclase sintética de Thread y anula su método run (), luego lo instancia y lo inicia.

Ivan
fuente
3
pensé que era una clase interna anónima
Kumar Abhinav
2
Tengo que estar de acuerdo con @KumarAbhinav. No todas las clases internas anónimas son sintéticas. Ver: xinotes.net/notes/note/1339
bvdb
Las clases internas anónimas no generan clases sintéticas en Oracle JDK 1.8.0_45, generan clases no sintéticas separadas con nombres de tipo Outer$1.class.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1

Una clase sintética no aparece en su código: está compuesta por el compilador. Por ejemplo, un método puente compuesto por un compilador en Java es típicamente sintético.

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");
    }
}

Usando el comando javap -verbose DateInterval, puede ver un método de puente:

public void setSecond(java.lang.Object);
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC

Esto fue hecho por el compilador; No aparece en su código.

JavaFresher
fuente
1

¿Qué es una clase sintética en Java?

Una syntheticclase es un .classarchivo generado por Java Compiler y no existe en el código fuente.

Ejemplo de uso de la syntheticclase: clase interna anónima

  • java.text.DigitList $ 1 es una syntheticclase y es una clase interna anónima dentro java.text.DigitList
  • Y no hay un archivo de código fuente llamado como DigitList$1.javapero es un archivo interno enDigitList.java

¿Por qué debería ser usado?

Es un mecanismo dentro de la lógica del compilador de Java para generar el .classarchivo

¿Como puedo usar lo?

No, los desarrolladores NO usan directamente.

El compilador de Java utiliza syntheticpara generar el .classarchivo, y luego JVM lee el.class archivo para ejecutar la lógica del programa.

Más detalles

  • Este artículo explicasynthetic clase en detalles
  • Este enlace enumera todas syntheticlas salidas de clase en JDK
Contento
fuente
el artículo es muy útil, gracias
JasonMing
0

Las construcciones sintéticas son clases, métodos, campos, etc. que no tienen una construcción correspondiente en el código fuente. Las construcciones sintéticas permiten a los compiladores de Java implementar nuevas características del lenguaje Java sin cambios en la JVM. Sin embargo, las construcciones sintéticas pueden variar entre diferentes implementaciones del compilador de Java, lo que significa que los archivos .class también pueden variar entre diferentes implementaciones.

Anoop Dixith
fuente
1
-1. El mismo texto, literalmente, se publicó en la respuesta dada un año antes que la suya [ stackoverflow.com/a/24271953/1144395] , y aún más esa respuesta también citó la referencia oficial donde se origina el texto, y proporcionó formato para una lectura más fácil . Por favor, no envíes preguntas codiciosas con respuestas claramente duplicadas.
naki