Classe synthétique en Java


143

Qu'est-ce qu'une classe synthétique en Java? Pourquoi devrait-il être utilisé? Comment puis-je l'utiliser?


1
Toutes les réponses «pas dans votre code» sont obsolètes avec Java 8, car les lambdas peuvent être implémentées sous forme de classes synthétiques (non anonymes).
OrangeDog

Pour être honnête, un lambda n'est toujours pas "strictement" une classe définie explicitement dans votre code. Donc, "pas dans votre code" est toujours valide. Le compilateur génère les classes synthétiques pour vous sans définition explicite dans votre code.
ManoDestra

Réponses:


15

Par exemple, lorsque vous avez une instruction switch, java crée une variable commençant par $. Si vous voulez voir un exemple de ceci, jetez un œil dans le reflet java d'une classe qui contient une instruction switch. Vous verrez ces variables lorsque vous avez au moins une instruction switch n'importe où dans la classe.

Pour répondre à votre question, je ne pense pas que vous puissiez accéder (autre que réflexion) aux classes synthétiques.

Si vous analysez une classe dont vous ne savez rien (via la réflexion) et que vous avez besoin de connaître des choses très spécifiques et de bas niveau sur cette classe, vous pouvez finir par utiliser des méthodes de réflexion Java qui ont à voir avec des classes synthétiques. La seule "utilisation" ici est d'obtenir plus d'informations sur la classe afin de l'utiliser de manière appropriée dans votre code.

(Si vous faites cela, vous construisez probablement une sorte de cadre que d'autres développeurs pourraient utiliser.)

Sinon, si vous n'utilisez pas la réflexion, il n'y a aucune utilisation pratique des classes synthétiques que je connaisse.


1
Oui, un exemple de code serait bon si vous pouviez fournir un exemple /
nanofarad

36
Cela ne répond pas à la question.
Dawood ibn Kareem

Pour le cas du commutateur, je ne suis pas sûr que cela se produise pour chaque commutateur, mais j'ai observé cela pour le commutateur avec des enums; le compilateur génère une classe anonyme avec un seul champ statique qui fournit un mappage Enum.ordinal () -> 1, 2, 3 ... (donc une séquence sans lacunes), puis une instruction lookupswitch exécute le commutateur sur cette séquence, pas directement sur les ordinaux.
Radim Vansa du

106

Java a la capacité de créer des classes au moment de l'exécution. Ces classes sont appelées classes synthétiques ou proxys dynamiques.

Voir http://java.sun.com/j2se/1.5.0/docs/guide/reflection/proxy.html pour plus d'informations.

D'autres bibliothèques open-source, telles que CGLIB et ASM vous permettent également de générer des classes synthétiques et sont plus puissantes que les bibliothèques fournies avec le JRE.

Les classes synthétiques sont utilisées par les bibliothèques AOP (Aspect Oriented Programming) telles que Spring AOP et AspectJ, ainsi que par les bibliothèques ORM telles que Hibernate.


6
Les proxys dynamiques ne sont pas des classes synthétiques.Preuve:Proxy.newProxyInstance(Runnable.class.getClassLoader(), new Class[]{Runnable.class}, (proxy, method, args1) -> null).getClass().isSynthetic() == false
Miha_x64

3
Le javadoc for java.lang.reflect.Member#isSyntheticdit: Renvoie true si ce membre a été introduit par le compilateur; renvoie false dans le cas contraire.
Guillaume Husta

Je pense que le javadoc pour java.lang.reflect.Member#isSyntheticest sans rapport avec la question initiale. Les membres sont des champs, des constructeurs et des méthodes. La question initiale concernait les classes synthétiques , pas les membres synthétiques. Dans Java 8, les expressions lambda donnent naissance à des classes synthétiques - je ne sais pas dans quelles autres circonstances elles peuvent survenir.
Fr Jeremy Krieg

54

Eh bien, j'ai trouvé la réponse à la première question sur google:

Une classe peut être marquée comme synthétique si elle est générée par le compilateur, c'est-à-dire qu'elle n'apparaît pas dans le code source.

Ceci est juste une définition de base mais je l'ai trouvée dans un fil de discussion et il n'y avait aucune explication. Toujours à la recherche d'un meilleur ...


15

classes / méthodes / champs synthétiques:

Ces éléments sont importants pour la machine virtuelle. Jetez un œil à l'extrait de code suivant:

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 六四 事件 法轮功, non, uniquement des méthodes d'accesseurs synthétiques.
Miha_x64

8

Selon cette discussion , bien que la spécification du langage décrit une propriété "isSynthetic" pour les classes, cela est pratiquement ignoré par les implémentations et n'est pas utilisé pour les proxys dynamiques ou les classes anonymes. Les champs synthétiques et les constructeurs sont utilisés pour implémenter des classes imbriquées (il n'y a pas de concept de classes imbriquées en byte code, uniquement en code source).

Je pense que le concept de classes synthétiques s'est simplement avéré inutile, c'est-à-dire que personne ne se soucie de savoir si une classe est synthétique. Avec les champs et les méthodes, il est probablement utilisé exactement à un seul endroit: pour déterminer ce qu'il faut afficher dans une vue de structure de classe IDE - vous voulez que les méthodes et les champs normaux apparaissent là-haut, mais pas ceux synthétiques utilisés pour simuler des classes imbriquées. OTOH, vous voulez que les classes anonymes apparaissent là-haut.


@OrangeDog: oui, c'est ce que j'ai écrit.
Michael Borgwardt

Cette réponse semble obsolète car java 8 - les références lambdas et méthodes utilisent cette fonctionnalité. J'ai ajouté une réponse démontrant que
Hulk

7

Ils sont créés par JVM au moment de l'exécution lorsqu'ils invoquent des membres privés de la classe interne à des fins de débogage

Les méthodes, champs, classe créés par JVM lors de l'exécution pour son exécution sont appelés Synthetic

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

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


Je suppose que vous voulez dire au moment de la compilation, et non au moment de l'exécution.
Mostowski Collapse le

@sathis, vouliez-vous dire javac, pas JVM?
Miha_x64

3

Des classes synthétiques ou des proxys dynamiques sont également utilisés par EasyMock pour créer des implémentations d'interfaces ou de classes abstraites au moment de l'exécution.

http://www.easymock.org/


2

Lorsque le compilateur Java compile certaines constructions, telles que les classes internes, il crée des constructions synthétiques ; ce sont des classes, des méthodes, des champs et d'autres constructions qui n'ont pas de construction correspondante dans le code source.
Utilisations: Les constructions synthétiques permettent aux compilateurs Java d'implémenter de nouvelles fonctionnalités du langage Java sans modifier la JVM. Cependant, les constructions synthétiques peuvent varier selon les différentes implémentations du compilateur Java, ce qui signifie que les fichiers .class peuvent également varier d'une implémentation à l'autre.
référence: docs.oracle.com


2

Comme plusieurs réponses l'ont déjà souligné, le compilateur est autorisé à générer diverses constructions (y compris des classes) qui ne correspondent pas directement à quelque chose dans le code source. Ceux-ci doivent être marqués comme synthétiques:

13.1. La forme d'un binaire

Une représentation binaire d'une classe ou d'une interface doit également contenir tous les éléments suivants:
[...]
11. Une construction émise par un compilateur Java doit être marquée comme synthétique si elle ne correspond pas à une construction déclarée explicitement ou implicitement dans le code source , sauf si la construction émise est une méthode d'initialisation de classe (JVMS §2.9).
[...]

Comme indiqué par @Holger dans un commentaire à une autre question, des exemples pertinents pour de telles constructions sont les objets Class représentant des références de méthode et des lambdas:

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

Production:

true
true

Bien que cela ne soit pas explicitement mentionné, cela découle de 15.27.4. Évaluation d'exécution des expressions Lambda :

La valeur d'une expression lambda est une référence à une instance d'une classe avec les propriétés suivantes: [...]

et le libellé presque identique pour les références de méthode ( 15.13.3. Évaluation d'exécution des références de méthode ).

Comme cette classe n'est explicitement mentionnée nulle part dans le code source, elle doit être synthétique.


1

Si je comprends bien, une classe synthétique est une classe générée à la volée, sans avoir à lui donner un nom explicite. Par exemple:

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

Cela crée une sous-classe synthétique de Thread et remplace sa méthode run (), puis l'instancie et la démarre.


3
Je pensais que c'était une classe intérieure anonyme
Kumar Abhinav

2
Je suis d'accord avec @KumarAbhinav. Toutes les classes internes anonymes ne sont pas synthétiques. Voir: xinotes.net/notes/note/1339
bvdb

Les classes internes anonymes ne génèrent pas de classes synthétiques sur Oracle JDK 1.8.0_45, elles génèrent des classes non synthétiques séparées avec des noms de type Outer$1.class.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1

Une classe synthétique n'apparaît pas dans votre code: elle est constituée par le compilateur. Par exemple, une méthode de pont constituée par un compilateur en java est généralement synthétique.

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

En utilisant la commande javap -verbose DateInterval, vous pouvez voir une méthode de pont:

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

Ceci a été créé par le compilateur; il n'apparaît pas dans votre code.


1

Qu'est-ce qu'une classe synthétique en Java?

Une syntheticclasse est un .classfichier généré par Java Compiler et n'existe pas dans le code source.

Exemple d'utilisation de la syntheticclasse: classe interne anonyme

  • java.text.DigitList $ 1 est une syntheticclasse et c'est une classe interne anonyme dans java.text.DigitList
  • Et il n'y a pas de fichier de code source nommé comme DigitList$1.javamais c'est un fichier interne dansDigitList.java

Pourquoi devrait-il être utilisé?

C'est un mécanisme à l'intérieur de la logique du compilateur Java pour générer le .classfichier

Comment puis-je l'utiliser?

Non, les développeurs ne l' utilisent PAS directement.

Le compilateur Java utilise syntheticpour générer un .classfichier, puis JVM lit le .classfichier pour exécuter la logique du programme.

Plus de détails

  • Cet article explique la syntheticclasse en détails
  • Ce lien répertorie toutes syntheticles sorties de classe dans JDK

l' article est très utile, merci
JasonMing

0

Les constructions synthétiques sont des classes, des méthodes, des champs, etc. qui n'ont pas de construction correspondante dans le code source. Les constructions synthétiques permettent aux compilateurs Java d'implémenter de nouvelles fonctionnalités du langage Java sans modifier la JVM. Cependant, les constructions synthétiques peuvent varier selon les différentes implémentations du compilateur Java, ce qui signifie que les fichiers .class peuvent également varier d'une implémentation à l'autre.


1
-1. Le même texte, textuellement, a été publié dans la réponse donnée un an avant la vôtre [ stackoverflow.com/a/24271953/1144395] , et cette réponse citait en outre la référence officielle d'où provient le texte et fournissait une mise en forme pour une lecture plus facile . Veuillez ne pas spammer les questions avec des réponses clairement dupliquées.
naki
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.