Synthetische Klasse in Java

143

Was ist eine synthetische Klasse in Java? Warum sollte es verwendet werden? Wie kann ich es benutzen?

andHapp
quelle
1
Alle "Nicht in Ihrem Code" -Antworten sind mit Java 8 veraltet, da Lambdas als synthetische (nicht anonyme) Klassen implementiert werden können.
OrangeDog
Um fair zu sein, ist ein Lambda immer noch nicht "streng" eine Klasse, die explizit in Ihrem Code definiert ist. "Nicht in Ihrem Code" ist also weiterhin gültig. Der Compiler generiert die synthetischen Klassen für Sie ohne explizite Definition in Ihrem Code.
ManoDestra

Antworten:

15

Wenn Sie beispielsweise eine switch-Anweisung haben, erstellt Java eine Variable, die mit einem $ beginnt. Wenn Sie ein Beispiel dafür sehen möchten, werfen Sie einen Blick in die Java-Reflexion einer Klasse, die eine switch-Anweisung enthält. Sie sehen diese Variablen, wenn Sie irgendwo in der Klasse mindestens eine switch-Anweisung haben.

Um Ihre Frage zu beantworten, glaube ich nicht, dass Sie auf die synthetischen Klassen zugreifen können (außer auf Reflexion).

Wenn Sie eine Klasse analysieren, von der Sie nichts wissen (über Reflektion) und sehr spezifische und einfache Dinge über diese Klasse wissen müssen, verwenden Sie möglicherweise Java-Reflektionsmethoden, die mit synthetischen Klassen zu tun haben. Die einzige "Verwendung" besteht darin, weitere Informationen über die Klasse zu erhalten, um sie in Ihrem Code angemessen zu verwenden.

(Wenn Sie dies tun, erstellen Sie wahrscheinlich ein Framework, das andere Entwickler verwenden könnten.)

Andernfalls, wenn Sie keine Reflexion verwenden, gibt es keine praktischen Verwendungen von synthetischen Klassen, die mir bekannt sind.

Milhous
quelle
1
Ja, Beispielcode wäre gut, wenn Sie ein Beispiel /
Nanofarad
36
Dies beantwortet die Frage nicht.
Dawood ibn Kareem
Für den Schalterfall bin ich nicht sicher, ob dies für jeden Schalter geschieht, aber ich habe dies für Schalter mit Aufzählungen beobachtet; Der Compiler generiert eine anonyme Klasse mit einem einzelnen statischen Feld, das eine Zuordnung Enum.ordinal () -> 1, 2, 3 ... (also eine Sequenz ohne Lücken) bereitstellt. Anschließend führt ein Lookupswitch-Befehl den Schalter für diese Sequenz aus, nicht direkt auf Ordnungszahlen.
Radim Vansa
106

Java kann zur Laufzeit Klassen erstellen. Diese Klassen werden als synthetische Klassen oder dynamische Proxies bezeichnet.

Weitere Informationen finden Sie unter http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html .

Andere Open-Source-Bibliotheken wie CGLIB und ASM ermöglichen ebenfalls das Generieren synthetischer Klassen und sind leistungsfähiger als die mit der JRE bereitgestellten Bibliotheken.

Synthetische Klassen werden von AOP-Bibliotheken (Aspect Oriented Programming) wie Spring AOP und AspectJ sowie von ORM-Bibliotheken wie Hibernate verwendet.

Andrew Newdigate
quelle
6
Dynamische Proxies sind keine synthetischen Klassen. Beweis:Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
Miha_x64
3
Das Javadoc für java.lang.reflect.Member#isSyntheticsagt: Gibt true zurück, wenn dieses Mitglied vom Compiler eingeführt wurde. Gibt sonst false zurück.
Guillaume Husta
Ich glaube, dass der Javadoc für java.lang.reflect.Member#isSyntheticdie ursprüngliche Frage irrelevant ist. Mitglieder sind Felder, Konstruktoren und Methoden. Die ursprüngliche Frage betraf synthetische Klassen , keine synthetischen Mitglieder. In Java 8 führen Lambda-Ausdrücke zu synthetischen Klassen - ich bin mir nicht sicher, unter welchen anderen Umständen sie auftreten können.
Pater Jeremy Krieg
54

Nun, ich habe die Antwort auf die erste Frage bei Google gefunden:

Eine Klasse kann als synthetisch markiert werden, wenn sie vom Compiler generiert wird, dh nicht im Quellcode erscheint.

Dies ist nur eine grundlegende Definition, aber ich habe sie in einem Forenthread gefunden und es gab keine Erklärung. Immer noch auf der Suche nach einem besseren ...

andHapp
quelle
15

synthetische Klassen / Methoden / Felder:

Diese Dinge sind wichtig für die VM. Schauen Sie sich das folgende Code-Snippet an:

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.
quelle
2
@CiroSantilli 事件 事件 2016 六四 事件 法轮功, nein, nur synthetische Zugriffsmethoden.
Miha_x64
8

Laut dieser Diskussion wird die Sprachspezifikation, obwohl sie eine "isSynthetic" -Eigenschaft für Klassen beschreibt, von Implementierungen weitgehend ignoriert und weder für dynamische Proxys noch für anonyme Klassen verwendet. Synthetische Felder und Konstruktoren werden verwendet, um verschachtelte Klassen zu implementieren (es gibt kein Konzept für verschachtelte Klassen im Bytecode, nur im Quellcode).

Ich denke, dass sich das Konzept der synthetischen Klassen einfach als nicht nützlich erwiesen hat, dh es interessiert niemanden, ob eine Klasse synthetisch ist. Bei Feldern und Methoden wird es wahrscheinlich genau an einer Stelle verwendet: um zu bestimmen, was in einer IDE-Klassenstrukturansicht angezeigt werden soll - Sie möchten, dass dort normale Methoden und Felder angezeigt werden, nicht jedoch die synthetischen, die zur Simulation verschachtelter Klassen verwendet werden. OTOH, Sie möchten, dass anonyme Klassen dort angezeigt werden.

Michael Borgwardt
quelle
@OrangeDog: Ja, das habe ich geschrieben.
Michael Borgwardt
Diese Antwort scheint veraltet zu sein, da Java 8 - Lambdas und Methodenreferenzen diese Funktion nutzen. Ich habe eine Antwort
Hulk
7

Sie werden von JVM zur Laufzeit erstellt, wenn sie private Mitglieder der inneren Klasse zum Debuggen aufrufen

Die Methoden, Felder und Klassen, die von JVM zur Laufzeit für die Ausführung erstellt wurden, werden als Synthetic bezeichnet

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

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

Sathis
quelle
Ich denke du meinst zur Kompilierungszeit und nicht zur Laufzeit.
Mostowski Zusammenbruch
@sathis, meintest du javac, nicht JVM?
Miha_x64
3

Auch synthetische Klassen oder dynamische Proxies werden von EasyMock verwendet, um zur Laufzeit Implementierungen von Schnittstellen oder abstrakten Klassen zu erstellen.

http://www.easymock.org/

user2427
quelle
2

Wenn der Java-Compiler bestimmte Konstrukte wie z. B. innere Klassen kompiliert, werden synthetische Konstrukte erstellt . Dies sind Klassen, Methoden, Felder und andere Konstrukte, deren Quellcode kein entsprechendes Konstrukt enthält.
Verwendung: Mit synthetischen Konstrukten können Java-Compiler neue Java-Sprachfunktionen implementieren, ohne Änderungen an der JVM vorzunehmen. Synthetische Konstrukte können jedoch zwischen verschiedenen Java-Compiler-Implementierungen variieren, was bedeutet, dass .class-Dateien auch zwischen verschiedenen Implementierungen variieren können.
Referenz: docs.oracle.com

Anavaras Lamurep
quelle
2

Wie bereits in verschiedenen Antworten erwähnt, kann der Compiler verschiedene Konstrukte (einschließlich Klassen) generieren, die nicht direkt mit etwas im Quellcode übereinstimmen. Diese müssen als synthetisch gekennzeichnet werden:

13.1. Die Form einer Binärdatei

Eine binäre Darstellung für eine Klasse oder Schnittstelle muss außerdem Folgendes enthalten:
[...]
11. Ein von einem Java-Compiler ausgegebenes Konstrukt muss als synthetisch markiert werden, wenn es keinem im Quellcode explizit oder implizit deklarierten Konstrukt entspricht , es sei denn, das ausgegebene Konstrukt ist eine Klasseninitialisierungsmethode (JVMS §2.9).
[...]

Wie von @Holger in einem Kommentar zu einer anderen Frage hervorgehoben, sind relevante Beispiele für solche Konstrukte die Klassenobjekte , die Methodenreferenzen und Lambdas darstellen:

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

Ausgabe:

true
true

Dies wird zwar nicht ausdrücklich erwähnt, folgt aber aus 15.27.4. Laufzeitauswertung von Lambda-Ausdrücken :

Der Wert eines Lambda-Ausdrucks bezieht sich auf eine Instanz einer Klasse mit den folgenden Eigenschaften: [...]

und der fast identische Wortlaut für Methodenreferenzen ( 15.13.3. Laufzeitbewertung von Methodenreferenzen ).

Da diese Klasse nirgendwo im Quellcode explizit erwähnt wird, muss sie synthetisch sein.

Hulk
quelle
1

Wenn ich es richtig verstehe, wird eine synthetische Klasse im laufenden Betrieb generiert, ohne dass sie explizit benannt werden muss. Beispielsweise:

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

Dadurch wird eine synthetische Unterklasse von Thread erstellt und die run () -Methode überschrieben. Anschließend wird sie instanziiert und gestartet.

Ivan
quelle
3
Ich dachte, es wäre eine anonyme innere Klasse
Kumar Abhinav
2
Ich muss @KumarAbhinav zustimmen. Nicht alle anonymen inneren Klassen sind synthetisch. Siehe: xinotes.net/notes/note/1339
bvdb
Anonyme innere Klassen generieren in Oracle JDK 1.8.0_45 keine synthetischen Klassen, sondern separate nicht synthetische Klassen mit Typnamen Outer$1.class.
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
1

Was ist eine synthetische Klasse in Java?

EIN synthetic Klasse ist eine .classvom Java Compiler generierte Datei im Quellcode nicht vorhanden ist.

Beispiel für die Verwendung von synthetic Klasse: Anonyme innere Klasse

  • java.text.DigitList $ 1 ist eine syntheticKlasse und eine anonyme innere Klasse in java.text.DigitList
  • Und es gibt keine Quellcodedatei mit dem Namen wie DigitList$1.java aber es ist eine innere Datei inDigitList.java

Warum sollte es verwendet werden?

Es ist ein Mechanismus innerhalb der Java-Compiler-Logik, um das zu generieren .class Datei

Wie kann ich es benutzen?

Nein, Entwickler tun es NICHT verwenden es direkt.

Java-Compiler syntheticzum Generieren verwenden.class Datei , und dann liest JVM die.class Datei, um die Programmlogik auszuführen.

Mehr Details

  • Dieser Artikel erklärtsynthetic Klasse im Detail
  • Dieser Link listet alle syntheticKlassen-Exits in JDK auf
glücklich
quelle
Der Artikel ist sehr nützlich, danke
JasonMing
0

Synthetische Konstrukte sind Klassen, Methoden, Felder usw., deren Quellcode kein entsprechendes Konstrukt enthält. Mit synthetischen Konstrukten können Java-Compiler neue Java-Sprachfunktionen implementieren, ohne die JVM zu ändern. Synthetische Konstrukte können jedoch zwischen verschiedenen Java-Compiler-Implementierungen variieren, was bedeutet, dass .class-Dateien auch zwischen verschiedenen Implementierungen variieren können.

Anoop Dixith
quelle
1
-1. Der gleiche Text wurde wörtlich in der Antwort veröffentlicht, die ein Jahr vor Ihrer [ stackoverflow.com/a/24271953/1144395] gegeben wurde , und in dieser Antwort wurde zusätzlich die offizielle Referenz zitiert, aus der der Text stammt, und die Formatierung zum leichteren Lesen bereitgestellt . Bitte spammen Sie nicht gierig Fragen mit eindeutig doppelten Antworten.
Naki
0

Eine synthetische Klasse erscheint nicht in Ihrem Code: Sie wird vom Compiler erstellt. Beispiel: Eine vom Compiler in Java erstellte Bridge-Methode ist normalerweise synthetisch.

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

Mit dem Befehl javap -verbose DateIntervalkönnen Sie eine Bridge-Methode anzeigen:

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

Dies wurde vom Compiler erfunden; es erscheint nicht in Ihrem Code.

JavaFresher
quelle