Classe sintetica in Java


143

Che cos'è una classe sintetica in Java? Perché dovrebbe essere usato? Come posso usarlo?


1
Tutte le risposte "non nel tuo codice" non sono aggiornate con Java 8, poiché lambdas può essere implementato come classi sintetiche (non anonime).
OrangeDog,

Ad essere onesti, un lambda non è ancora "rigorosamente" una classe definita esplicitamente nel tuo codice. Pertanto, "non nel tuo codice" è ancora valido. Il compilatore genera le classi sintetiche per te senza una definizione esplicita nel codice.
ManoDestra,

Risposte:


15

Ad esempio, quando si dispone di un'istruzione switch, java crea una variabile che inizia con $. Se vuoi vedere un esempio di questo, dai un'occhiata al riflesso Java di una classe che contiene un'istruzione switch. Vedrai queste variabili quando hai almeno un'istruzione switch in qualsiasi punto della classe.

Per rispondere alla tua domanda, non credo che tu sia in grado di accedere (oltre alla riflessione) alle classi sintetiche.

Se stai analizzando una classe di cui non sai nulla (tramite la riflessione) e hai bisogno di sapere cose molto specifiche e di basso livello su quella classe, potresti finire con l'uso di metodi di riflessione Java che hanno a che fare con le classi sintetiche. L'unico "uso" qui è ottenere maggiori informazioni sulla classe per usarla in modo appropriato nel tuo codice.

(Se lo stai facendo, probabilmente stai costruendo un quadro di alcuni tipi che altri sviluppatori potrebbero usare.)

Altrimenti, se non stai usando la riflessione, non ci sono usi pratici di classi sintetiche che conosco.


1
Sì, il codice di esempio sarebbe utile se tu potessi fornire un esempio /
nanofarad

36
Questo non risponde alla domanda.
Dawood ibn Kareem,

Per il caso switch, non sono sicuro che ciò accada per ogni switch, ma l'ho osservato per switch con enum; il compilatore genera una classe anonima con un singolo campo statico che fornisce una mappatura Enum.ordinal () -> 1, 2, 3 ... (quindi una sequenza senza spazi vuoti), quindi un'istruzione switchups avvia l'interruttore su questa sequenza, non direttamente sugli ordinali.
Radim Vansa,

106

Java ha la capacità di creare classi in fase di esecuzione. Queste classi sono conosciute come classi sintetiche o proxy dinamici.

Vedere http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html per ulteriori informazioni.

Altre librerie open-source, come CGLIB e ASM, consentono anche di generare classi sintetiche e sono più potenti delle librerie fornite con JRE.

Le classi sintetiche sono utilizzate dalle librerie AOP (Aspect Oriented Programming) come Spring AOP e AspectJ, nonché dalle librerie ORM come Hibernate.


6
I proxy dinamici non sono classi sintetiche. Prova:Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
Miha_x64,

3
Il javadoc per java.lang.reflect.Member#isSyntheticdice: restituisce vero se questo membro è stato introdotto dal compilatore; restituisce false altrimenti.
Guillaume Husta,

Credo che il javadoc java.lang.reflect.Member#isSyntheticsia irrilevante per la domanda originale. I membri sono campi, costruttori e metodi. La domanda originale riguardava le classi sintetiche , non i membri sintetici. In Java 8, le espressioni lambda danno origine a classi sintetiche - non sono sicuro di quali altre circostanze possano sorgere.
P. Jeremy Krieg,

54

Bene ho trovato la risposta alla prima domanda su google:

Una classe può essere contrassegnata come sintetica se viene generata dal compilatore, ovvero non viene visualizzata nel codice sorgente.

Questa è solo una definizione di base, ma l'ho trovata in un thread del forum e non c'erano spiegazioni. Sto ancora cercando uno migliore ...


15

classi / metodi / campi sintetici:

Queste cose sono importanti per la VM. Dai un'occhiata al seguente frammento di codice:

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

2
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功, no, solo metodi di accesso sintetici.
Miha_x64,

8

Secondo questa discussione , sebbene la specifica del linguaggio descriva una proprietà "isSintetica" per le classi, questa viene praticamente ignorata dalle implementazioni e non viene utilizzata per proxy dinamici o classi anonime. I campi sintetici e i costruttori vengono utilizzati per implementare le classi nidificate (non esiste il concetto di classi nidificate nel codice byte, solo nel codice sorgente).

Penso che il concetto di classi sintetiche abbia semplicemente dimostrato di non essere utile, cioè a nessuno importa se una classe sia sintetica. Con campi e metodi, è probabilmente usato esattamente in un punto: per determinare cosa mostrare in una vista della struttura di classe IDE - vuoi che vengano mostrati metodi e campi normali, ma non quelli sintetici usati per simulare le classi nidificate. OTOH, vuoi che vengano mostrate lezioni anonime lì.


@OrangeDog: sì, è quello che ho scritto.
Michael Borgwardt,

Questa risposta sembra essere obsoleta poiché java 8 - lambdas e riferimenti ai metodi fanno uso di questa funzione. Ho aggiunto una risposta che lo dimostra
Hulk,

7

Sono creati da JVM in fase di esecuzione quando invocano membri privati ​​della classe interna a scopo di debug

I metodi, i campi, la classe creata da JVM durante l'esecuzione per il suo scopo di esecuzione sono chiamati Synthetic

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

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


Immagino che intendi in fase di compilazione e non in fase di esecuzione.
Mostowski Collapse

@sathis, intendevi javac, non JVM?
Miha_x64,

3

Anche le classi sintetiche o i proxy dinamici vengono utilizzati da EasyMock per creare implementazioni di interfacce o classi astratte in fase di esecuzione.

http://www.easymock.org/


2

Quando il compilatore Java compila determinati costrutti, come le classi interne, crea costrutti sintetici ; si tratta di classi, metodi, campi e altri costrutti che non hanno un costrutto corrispondente nel codice sorgente.
Usi: costrutti sintetici consentono ai compilatori Java di implementare nuove funzionalità del linguaggio Java senza modifiche alla JVM. Tuttavia, i costrutti sintetici possono variare tra le diverse implementazioni del compilatore Java, il che significa che anche i file .class possono variare tra le diverse implementazioni.
riferimento: docs.oracle.com


2

Come hanno già indicato varie risposte, al compilatore è consentito generare vari costrutti (comprese le classi) che non corrispondono direttamente a qualcosa nel codice Souce. Questi devono essere contrassegnati come sintetici:

13.1. La forma di un binario

Una rappresentazione binaria per una classe o un'interfaccia deve contenere anche tutti i seguenti elementi:
[...]
11. Un costrutto emesso da un compilatore Java deve essere contrassegnato come sintetico se non corrisponde a un costrutto dichiarato esplicitamente o implicitamente nel codice sorgente , a meno che il costrutto emesso non sia un metodo di inizializzazione di classe (JVMS §2.9).
[...]

Come sottolineato da @Holger in un commento a un'altra domanda, esempi rilevanti per tali costrutti sono gli oggetti Class che rappresentano riferimenti a metodi e lambdas:

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

Produzione:

true
true

Sebbene ciò non sia esplicitamente menzionato, segue il 15.27.4. Valutazione run-time delle espressioni lambda :

Il valore di un'espressione lambda è un riferimento a un'istanza di una classe con le seguenti proprietà: [...]

e la dicitura quasi identica per i riferimenti ai metodi ( 15.13.3. Valutazione run-time dei riferimenti ai metodi ).

Poiché questa classe non è esplicitamente menzionata in nessun punto del codice sorgente, deve essere sintetica.


1

Se lo capisco bene, una classe sintetica viene generata al volo, senza dover dargli un nome esplicito. Per esempio:

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

Questo crea una sottoclasse sintetica di Thread e sovrascrive il suo metodo run (), quindi lo crea un'istanza e lo avvia.


3
pensavo fosse una classe interna anonima
Kumar Abhinav,

2
Sono d'accordo con @KumarAbhinav. Non tutte le classi interne anonime sono sintetiche. Vedi: xinotes.net/notes/note/1339
bvdb l'

Le classi interne anonime non generano classi sintetiche su Oracle JDK 1.8.0_45, generano classi separate non sintetiche con nomi di tipo Outer$1.class.
Ciro Santilli 11 冠状 病 六四 事件 法轮功

1

Una classe sintetica non appare nel tuo codice: è composta dal compilatore. Ad esempio, un metodo bridge creato dal compilatore in Java è in genere sintetico.

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 il comando javap -verbose DateInterval, puoi vedere un metodo bridge:

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

Questo è stato creato dal compilatore; non appare nel tuo codice.


1

Che cos'è una classe sintetica in Java?

Una syntheticclasse è un .classfile generato da Java Compiler e non esiste nel codice sorgente.

Esempio di utilizzo della syntheticclasse: classe interna anonima

  • java.text.DigitList $ 1 è una syntheticclasse ed è una classe interna anonima all'interno di java.text.DigitList
  • E non esiste un file di codice sorgente chiamato like DigitList$1.javama è un file interno inDigitList.java

Perché dovrebbe essere usato?

È un meccanismo all'interno della logica del compilatore Java per generare il .classfile

Come posso usarlo?

No, gli sviluppatori NON lo usano direttamente.

Il compilatore Java utilizza syntheticper generare il .classfile, quindi JVM legge il .classfile per eseguire la logica del programma.

Più dettagli

  • Questo articolo spiega la syntheticclasse in dettaglio
  • Questo link elenca tutte syntheticle uscite di classe in JDK

l' articolo è molto utile, grazie
JasonMing

0

I costrutti sintetici sono classi, metodi, campi ecc. Che non hanno un costrutto corrispondente nel codice sorgente. I costrutti sintetici consentono ai compilatori Java di implementare nuove funzionalità del linguaggio Java senza modifiche alla JVM. Tuttavia, i costrutti sintetici possono variare tra le diverse implementazioni del compilatore Java, il che significa che anche i file .class possono variare tra le diverse implementazioni.


1
-1. Lo stesso testo, letteralmente, è stato pubblicato nella risposta data un anno prima del tuo [ stackoverflow.com/a/24271953/1144395] , e inoltre la risposta citava ulteriormente il riferimento ufficiale da cui proviene il testo e forniva la formattazione per una lettura più semplice . Per favore, non invidiare avidamente le domande con risposte chiaramente duplicate.
naki,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.