IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

[enum] Ecrire un singleton en Java 5.0+


Sujet :

Langage Java

  1. #1
    Membre actif
    Inscrit en
    Novembre 2006
    Messages
    129
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 129
    Par défaut [enum] Ecrire un singleton en Java 5.0+
    Bonjour,

    Je trouve l'écriture des singletons en Java relativement chiante, qui plus est quand il s'agit de faire du multithread, et je m'étonne du côté bricolage de la manoeuvre puisqu'à aucun moment la JVM n'est au courant de cette "caractéristique" de la classe...

    N'y a-t-il pas un moyen à l'aide des énumérations de Java 5 de faire que la JVM assure comme une grande l'unicité de l'instance? Je m'explique :

    Au lieu d'utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public class MonSingleton {
      private static MonSingleton instanceUnique;
      private MonSingleton() { ... }
      public static MonSingleton getInstance() {
        if (instanceUnique == null)
          instanceUnique = new MonSingleton();
        return instanceUnique;
      }
    ...
    }
    Utiliser une énumération JSE5 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public enum MonSingleton {
      INSTANCE;
      MonSingleton() { ... }
     
      // Juste pour faire zoli
      public static MonSingleton getInstance() { return INSTANCE; }
    ...
    }
    Est-ce que c'est une bonne idée? Pourquoi?
    Ou alors j'ai rien compris à l'utilisation des énums?

    Merci les zamis
    ++

  2. #2
    Membre chevronné Avatar de gronono
    Inscrit en
    Novembre 2003
    Messages
    457
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Novembre 2003
    Messages : 457
    Par défaut
    Effectivement, cela peut être une bonne idée.

    Les valeurs des enums ne possèdent qu'une seul instance en théorie.
    Je pense qu'il vaudrait vérifier les spécs concernant les enums pour vérifier que la réalité est la même.

    Il y a quand même un problème sémantique. Le mot clé "enum" indique une énumération. C'est un peu bizarre de voir une énumération contenant une seule valeur et de s'apercevoir qu'en réalité c'est un singleton.

    A+
    Gronono

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    C'est un peu bizarre, certes, mais astucieux ! Cela ne devrait - à priori - pas poser de problème de synchronisation, mais le lazy loading n'est pas possible dans ce cas.

    C'est à dire que typiquement, nous avons exactement la même chose que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class MonSingleton {
      public static final MonSingleton INSTANCE = new MonSingleton();
      public static MonSingleton getInstance () {
        return INSTANCE;
      }
      private MonSingleton () {
        ...
      }
    }

  4. #4
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Je ne vois pas trop l'intérêt d'utiliser une enum


    Pourquoi ne pas simplement utiliser le ClassLoader pour s'assurer de l'unicité du singleton :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class MonSingleton {
    	private static final MonSingleton INSTANCE = new MonSingleton();
     
    	private MonSingleton() {
    		// ...
    	}
     
    	public static MonSingleton getInstance() {
    		return INSTANCE;
    	}
    }
    L'instance du singleton sera créé lors du chargement de la classe...

    a++

    PS : le code du singleton que tu donnes n'est pas thread-safe

    [edit] grillé

  5. #5
    Membre actif
    Inscrit en
    Novembre 2006
    Messages
    129
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 129
    Par défaut
    Pourquoi ne pas simplement utiliser le ClassLoader pour s'assurer de l'unicité du singleton
    ché pa! je trouve ça moche

    sinon merci pour vos réactions, c'est vrai qu'il y avait deux trois trucs auxquels j'avais pas pensé (notamment le cas de l'instanciation on demand )...

    par contre, si ce code n'est pas thread-safe, ça veut dire que les énumérations classiques ne le sont pas non plus?

    du coup, je me pose une autre question plus générale, qu'apportent réellement les énumérations si finalement des membres statiques sont aussi bien?

    en tout cas vous m'enlèverez pas de l'esprit qu'un singleton est un cas particulier d'énumération (essayez donc )

  6. #6
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Ce qui suit est une reflection (je ne sais pas si c'est vrai concernant les enums)

    Un sinleton aujourd'hui peut ne pas l'être selon l'architecture de l'application.
    En effet si l'application met en jeu une hierarchie complexe de classloader (exemple un serveur J2EE avec ces containers) alors ton singleton a de forte chance d'etre instancié plusieurs fois.

    J'image (là commence mon interpretation) qu'un Enum suis les mêmes loi qu'une classe standard vis à vis des classloaders (est-ce vrai ?)
    Dans ce cas plusieurs instances de ton singleton pourront exister pour les même raisons que précedemment.

    Par contre même si MonEnum.INSTANCE == MonEnum.INSTANCE met en jeu deux instances créées par des classLoaders différents, cette égalité retournera "true" car il s'agit d'une spec des Enums.

    Du coups, j'ai l'impression que cette solution est pire que la 1ere dans le sens où même si plusieurs instances existent, tu n'arriveras pas à t'en rendre compte.


    Maintenant, si à l'inverse, les Enum ne suivent pas les mêmes "loi" que les classes normales pour être chargés et que cela permet de se limiter à une instance même dans le cas de plusieurs classloader alors l'interêt est certain.

    Je vais me renseigner sur le fonctionnement interne des Enum car ca a piqué ma curiosité.

    PS: Conceptuellement une entrée d'une Enumeration est logiquement immuable une fois créée, ce qui permet justement d'accepter le "hack" sur l'opérateur == dans le cas de 2 énumerations chargées par des classloaders differents

    EDIT: Mes spéculations / hypothéses qui se révélent fausses (méaculpa)
    Séb.

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    Citation Envoyé par palnap Voir le message
    par contre, si ce code n'est pas thread-safe, ça veut dire que les énumérations classiques ne le sont pas non plus?
    Il voulait parler de la manière dont tu as implémenté le singleton en utilisant une classe. Le code du singleton-enum est thread-safe, lui.

  8. #8
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par palnap Voir le message
    par contre, si ce code n'est pas thread-safe, ça veut dire que les énumérations classiques ne le sont pas non plus?
    Les enumérations classiques sont thread-safe car elles sont initialisé par le classloader.

    Pour le code non thread-safe je parlais bien sûr de celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class MonSingleton {
      private static MonSingleton instanceUnique;
      private MonSingleton() { ... }
      public static MonSingleton getInstance() {
        if (instanceUnique == null)
          instanceUnique = new MonSingleton();
        return instanceUnique;
      }
    ...
    }
    Si tu appelles getInstance() simultanément depuis plusieurs threads alors que l'instance n'est pas créé, tu pourrais entrer plusieurs fois dans le if et donc appeler plusieurs fois le constructeur.



    Citation Envoyé par palnap Voir le message
    du coup, je me pose une autre question plus générale, qu'apportent réellement les énumérations si finalement des membres statiques sont aussi bien?
    La gestion "propre" des énumérations, avec :
    • Une vérification forte des types et des valeurs (impossible de créer des valeurs incorrectes).
    • Gestion des égalités.
    • Gestion propre de la (dé-)sérialisation (sans créer de nouvelle instance).
    • + différents outils facilitant la gestion (l'affichage donne le nom de l'énum et non pas sa valeur, méthode d'accès par nom...)
    • ...



    Citation Envoyé par palnap Voir le message
    en tout cas vous m'enlèverez pas de l'esprit qu'un singleton est un cas particulier d'énumération (essayez donc )
    Peut-être mais la plupart des "fonctionnalités" des enums sont inutiles et il est alors possible de "casser" l'accès en utilisant MonSingleton.INSTANCE au lieu de MonSingleton.getInstance()...


    Citation Envoyé par divxdede Voir le message
    PS: Conceptuellement une entrée d'une Enumeration est logiquement immuable une fois créée,
    Attention une enum n'est pas forcément immuable (même si cela devrait logiquement être le cas) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	enum MonEnumPasImmuable {
    		VALUE1, VALUE2, VALUE3;
     
    		private int value;
     
    		public int getValue() {
    			return value;
    		}
     
    		public void setValue(int value) {
    			this.value = value;
    		}
    	}
    Par contre la notion d'égalité des enums se base sur l'identité et non pas sur les propriétées des valeurs...


    a++

  9. #9
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Une énumeration est immuable dans le sens où elle aura toujours les mêmes entrées.
    Cependant ces entrées ne sont pas forcement immuable car effectivement comme le montre adiGuba, tu peux ajouter des setters & cie.

    Cependant, il me semble important d'essayer d'éviter ce genre de cas qui me semble dangereux et contraire au principe d'une énumération.

  10. #10
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Oui tout à fait mais c'est sur le sens de immuable qu'on est pas d'accord.


    Pour moi immuable veut dire : "dès lors qu'une instance est créé, on ne peut plus modifié ses valeurs (à moins de recréer une instance)".

    Et là ce n'est pas forcément le cas des enums.


    Par contre il est vrai qu'il est impossible de créer de nouvelle instance d'une enum, ce qui est je pense ce que tu voulait dire

    a++

  11. #11
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Immuable à le même sens pour moi

    En fait la premiere fois je disais

    Citation Envoyé par divxdede
    PS: Conceptuellement une entrée d'une Enumeration est logiquement immuable une fois créée,
    le logiquement était là pour insister sur le fait que ce n'est pas une obligation mais plutôt un conseil.

    Ensuite ma remarque:
    Citation Envoyé par divxdede
    Une énumeration est immuable dans le sens où elle aura toujours les mêmes entrées.
    L'enumération est en elle même immuable (l'ensemble ne bouge pas).
    Ce sont les entrées de l'énumeration qui peuvent ne pas l'être mais devraient l'être la plupart du temps.

  12. #12
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par divxdede Voir le message
    le logiquement était là pour insister sur le fait que ce n'est pas une obligation mais plutôt un conseil.
    Ok j'avais tout compris de travers alors

    On est d'accord

    a++

  13. #13
    Membre expérimenté
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    156
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 156
    Par défaut
    Citation Envoyé par divxdede Voir le message
    Par contre même si MonEnum.INSTANCE == MonEnum.INSTANCE met en jeu deux instances créées par des classLoaders différents, cette égalité retournera "true" car il s'agit d'une spec des Enums.
    C'est faux. Ou as tu lu ça dans les specs ?

  14. #14
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Citation Envoyé par phantomass Voir le message
    C'est faux. Ou as tu lu ça dans les specs ?
    je le dit plus haut !! je ne sais pas si c'est vrai, il s'agit uniquement de pur spéculation, j'admet avoir écrit une phrase un peu "franche" alors que ce n'était qu'une hypothése.

  15. #15
    Membre expérimenté
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    156
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 156
    Par défaut
    Ok.
    Je me permet donc de préciser que c'était faux.

  16. #16
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Citation Envoyé par phantomass Voir le message
    Ok.
    Je me permet donc de préciser que c'était faux.
    Je viens effectivement de verifier.
    Cela est d'ailleurs dangereux car par nature on test les énums entre eux avec l'opérateur == et celui-ci peur retourner faux (à tord) dans un environnement avec une hiérarchie de classloaders tel qu'un serveur J2EE

    PS: j'ai édité mon 1er message afin d'indiquer ce qui est faux dans mes hypothéses de ce matin.

  17. #17
    Membre expérimenté
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    156
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 156
    Par défaut
    Tu introduis un faux problème ou du moins un fausse crainte.
    Chaque attribut d'un enum est en réalité une instance de classe. On s'en doute bien.
    La spécification du langage Java exprime bien le fait que 2 instances sont égale si elles ont le même type runtime . C'est à dire qu'elles sont de la même classe, chargé par le même classloader.
    http://java.sun.com/docs/books/jls/t...ues.html#4.3.4
    Le problème que tu mets en avant est vrai mais valable pour tout les types de classes et il n y aurait pas de raison que les énumérations y fassent exception.
    Java 5 (hors annotation) a surtout introduit du sucre syntaxique mais le bytecode généré par le compilateur concernant l'usage des enums, de l'autoboxing ou des generics, est quasi équivalent à ce que peut produire un développeur en java 1.5

Discussions similaires

  1. Ecrire log Oracle via java
    Par Diablo_22 dans le forum Persistance des données
    Réponses: 1
    Dernier message: 10/07/2012, 14h20
  2. Ecrire un modèle avec Java
    Par router_ dans le forum Eclipse
    Réponses: 0
    Dernier message: 15/07/2010, 19h15
  3. ecrire le ping en java
    Par ikconde dans le forum Entrée/Sortie
    Réponses: 1
    Dernier message: 21/03/2007, 13h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo