¿Qué es una clase sintética en Java? ¿Por qué debería ser usado? ¿Como puedo usar lo?
¿Qué es una clase sintética en Java? ¿Por qué debería ser usado? ¿Como puedo usar lo?
Respuestas:
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.
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.
Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
java.lang.reflect.Member#isSynthetic
dice: Devuelve verdadero si este miembro fue introducido por el compilador; devuelve falso de lo contrario.
java.lang.reflect.Member#isSynthetic
es 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.
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 ...
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() {
}
}
}
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í.
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/
EasyMock también utiliza clases sintéticas o proxys dinámicos para crear implementaciones de interfaces o clases abstractas en tiempo de ejecución.
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
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:
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.
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.
Outer$1.class
.
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.
¿Qué es una clase sintética en Java?
Una synthetic
clase es un .class
archivo generado por Java Compiler y no existe en el código fuente.
Ejemplo de uso de la synthetic
clase: clase interna anónima
synthetic
clase y es una clase interna anónima dentro java.text.DigitListDigitList$1.java
pero 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 .class
archivo
¿Como puedo usar lo?
No, los desarrolladores NO usan directamente.
El compilador de Java utiliza synthetic
para generar el .class
archivo, y luego JVM lee el.class
archivo para ejecutar la lógica del programa.
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.