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 :

enums avec références croisées


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juillet 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2010
    Messages : 19
    Par défaut enums avec références croisées
    Bonjour,
    Quelque chose m'échappe dans le processus d'instanciation des enum.
    J'ai deux enum différentes, chacune possède des attributs du type de l'autre, et l'une des deux ne se construit pas correctement.
    Exemple simplifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    public class Test {
     
    	private static enum E1 {
    		A(E2.A), B(E2.B);
     
    		public E2 e2;
     
    		private E1(E2 e2) {
    			this.e2 = e2;
    		}
    	}
     
    	private static enum E2 {
    		A(E1.A), B(E1.B);
     
    		public E1 e1;
     
    		private E2(E1 e1) {
    			this.e1 = e1;
    		}
    	}
     
    	public static void main(String[] args) {
    		for (E1 e1 : E1.values()) {
    			System.out.print(e1.e2 + "\n");
    		}
    		for (E2 e2 : E2.values()) {
    			System.out.print(e2.e1 + "\n");
    		}
    	}
     
    }
    renvoie :
    A
    B
    null
    null

    Pourtant, pas d'erreur à la compilation. Est-ce que ce mécanisme est licite ? Il y a-t-il un moyen de contourner cela ?

    Merci pour votre aide.

  2. #2
    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,


    C'est normal car tu es croisés dans les 2 sens. E1 a besoin de E2 qui a lui-même besoin de E1...

    A l'initialisation il y a forcément un moment où un des champs n'est pas encore valide :

    • Tu charges l'enum E1, et donc cela crée les attributs static A & B non initialisé (=null).
    • Les champs static A & B sont initialisés. Donc cela appelle le constructeur E1()
    • Ce dernier charge l'enum E2, qui utilisent l'enum E1 alors qu'elle n'est pas encore totalement initialisé, et tu récupères donc les valeurs nulles.
    • Les constructeurs de E1 sont finalement exécutés, et la classe E1 est enfin correctement initialisé, mais tu accèdes aux données trop tôt.





    Quelle est la raison qui t'amène à un tel croisement ?

    a++

    PS : Et attention aux attributs public dans les enums. Ces dernières devrait logiquement être immuable...

  3. #3
    Membre averti
    Inscrit en
    Juillet 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2010
    Messages : 19
    Par défaut
    Quelle est la raison qui t'amène à un tel croisement ?
    Je voulais utiliser quelque chose de ce genre pour diviser un groupe d'éléments en sous-groupes.
    Comme le groupe principal et les sous-groupes sont finis et figés, je trouvais logique d'utiliser des enum :

    Enum A Enum B
    - A1 \
    - A2 -----B1
    - A3 /

    - A4 \
    - A5 -----B2
    - A6 /

    - A7 \
    - A8 -----B3
    - A9 /

    Problème si je veux à partir de A4 retrouver les frères A5 et A6 je suis obligé de déclarer A dans B et B dans A.
    De ce que tu dis ça ne me paraît pas possible de cette façon.
    Merci à toi.

  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
    Citation Envoyé par lnotray Voir le message
    Problème si je veux à partir de A4 retrouver les frères A5 et A6 je suis obligé de déclarer A dans B et B dans A.
    Ben il te suffit de donner le lien dans un sens seulement. Par exemple uniquement en liant le parent :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public enum B {
        B1, B2, B3;
    }
     
     
     
    public enum A {
        A1(B1), A2(B1), A3(B1),
        A4(B2), A5(B2), A6(B2),
        A7(B3), A8(B3), A9(B3);
     
        private B parent;
     
        private A(B parent) {
            this.parent = parent;
        }
     
        public static static List<A> getByParent(B b) {
            ArrayList<A> list = new ArrayList<A>();
            foreach (A a : A.values()) {
                if (a.parent==b) {
                    list.add(a);
                }
            }
            list.trimToSize();
            return list;
        }
    }
    a++

  5. #5
    Membre averti
    Inscrit en
    Juillet 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2010
    Messages : 19
    Par défaut
    ça se tient, merci.
    je pensais qu'il existait quelque chose de plus esthétique.

  6. #6
    Membre averti
    Inscrit en
    Juillet 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Juillet 2010
    Messages : 19
    Par défaut
    En fait après réflexion je préfère cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    public class Test {
    	private static enum E1 {
    		A {
    			@Override
    			public E2 getE2() {
    				return E2.A;
    			}
    		},
    		B {
    			@Override
    			public E2 getE2() {
    				return E2.B;
    			}
    		};
    		public abstract E2 getE2();
    	}
     
    	private static enum E2 {
    		A {
    			@Override
    			public E1 getE1() {
    				return E1.A;
    			}
    		},
    		B {
    			@Override
    			public E1 getE1() {
    				return E1.B;
    			}
    		};
    		public abstract E1 getE1();
    	}
     
    	public static void main(String[] args) {
    		for (E1 e1 : E1.values()) {
    			System.out.println(e1.getE2());
    		}
    		for (E2 e2 : E2.values()) {
    			System.out.println(e2.getE1());
    		}
    	}
    }
    Comme cela on n'a plus besoin de se préoccuper de l'ordonnancement des constructeurs, puisqu'ils n'ont plus d'argument (je ne savais pas que c'était possible).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Références croisées imprécises avec le package titlesec
    Par zeddiccus dans le forum Mise en forme
    Réponses: 3
    Dernier message: 11/09/2013, 09h14
  2. références croisées avec import
    Par yves2 dans le forum Général Python
    Réponses: 3
    Dernier message: 11/03/2012, 14h26
  3. Problème de déclaration avec références croisées
    Par lpierard dans le forum Débuter
    Réponses: 2
    Dernier message: 20/11/2009, 16h10

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