67 votes

Comment values () est-il implémenté pour Java 6 enums?

En Java, vous pouvez créer un enum comme suit:

public enum Letter {
    A, B, C, D, E, F, G;

    static {
       for(Letter letter : values()) {
          // do something with letter
       }
    }
}

Cette question concerne les "valeurs" ()" la méthode. Plus précisément, comment est-il mis en œuvre? Habituellement, je pouvais sauter à la source des classes Java à l'aide de F3 ou CTRL+Clic dans Eclipse (même pour des classes comme Chaîne de Caractères, Entier, et même Enum). Il est possible d'afficher la source de l'autre enum méthodes (p. ex., valueOf(String)).

"Les valeurs de()" créer un nouveau tableau à chaque fois qu'il est invoqué? Si je l'affecter à une variable locale et de modifier l'un des éléments, ce qui se passe (ce qui n'affecte pas la valeur retournée par les valeurs), ce qui implique qu'un nouveau tableau est alloué à chaque fois).

Est le code natif? Ou ne la JVM / compilateur de traiter spécialement, ne revenant à une nouvelle instance de valeurs() quand il ne peut pas prouver qu'il ne sera pas modifié.

Merci à l'avance.

Cheers, LES

107voto

lucasmo Points 1574

Fondamentalement, le compilateur (javac) traduit votre enum en un tableau statique contenant toutes vos valeurs au moment de la compilation. Lorsque vous appelez values (), cela vous donne une copie .clone'd () de ce tableau.

Étant donné cette simple énumération:

 public enum Stuff {
   COW, POTATO, MOUSE;
}
 

Vous pouvez réellement regarder le code généré par Java:

 public enum Stuff extends Enum<Stuff> {
    /*public static final*/ COW /* = new Stuff("COW", 0) */,
    /*public static final*/ POTATO /* = new Stuff("POTATO", 1) */,
    /*public static final*/ MOUSE /* = new Stuff("MOUSE", 2) */;
    /*synthetic*/ private static final Stuff[] $VALUES = new Stuff[]{Stuff.COW, Stuff.POTATO, Stuff.MOUSE};

    public static Stuff[] values() {
        return (Stuff[])$VALUES.clone();
    }

    public static Stuff valueOf(String name) {
        return (Stuff)Enum.valueOf(Stuff.class, name);
    }

    private Stuff(/*synthetic*/ String $enum$name, /*synthetic*/ int $enum$ordinal) {
        super($enum$name, $enum$ordinal);
    }
}
 

Vous pouvez voir comment javac "traduit" vos classes en créant un répertoire temporaire et en exécutant:

 javac -d <output directory> -XD-printflat filename.java
 

2voto

Janusz Points 52607

Si vous pouvez l'affecter à une variable locale la seule chose que vous pouvez modifier est l'attribution d'une autre enum pour cette variable. Cela ne changera pas l'enum lui-même parce que vous êtes seulement à changer l'objet de votre références à des variables.

Il semble que les énumérations sont en fait des singletons de sorte que seulement un seul élément de chaque enum peut exister dans vous de tout programme de ce fait l'opérateur == juridiques pour les énumérations.

Donc, il n'y a pas de problème de performance, et vous ne pouvez pas accidentellement changer quelque chose dans votre enum définition.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X