Comment est-valeurs() mis en œuvre pour Java 6 énumérations?
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)).
Ne "valeurs" ()" 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 (clairement 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é.
Vous devez vous connecter pour publier un commentaire.
Fondamentalement, le compilateur (javac) traduit votre enum dans un tableau statique contenant tous vos valeurs au moment de la compilation. Lorsque vous appelez les valeurs de(), il vous donne une .clone avais() copie de ce tableau.
Compte tenu de cette simple enum:
Fait vous pouvez regarder le code Java génère:
Vous pouvez regarder comment javac 'traduit' vos classes en faisant un répertoire temporaire et en cours d'exécution:
synthetic
.values()
méthodeclone()
le tableau$VALUES
? Pourquoi ne pas tout simplement l'envoyer directement?-XD-printflat
. Très utile pour comprendre le fonctionnement interne de ces choses. Il est dommage que cette chose n'est pas mieux documentées. Merci de me mettre au courant de ce!.values()
méthode. À partir de ce que vous dites, il semble que ce n'est pas une méthode commune à tous les énumérations, mais plutôt un distinct méthode qui existe dans chaque, a déclaré enum et qui n'a rien en commun avec le.values()
méthode dans tous les autres déclaré enum.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.
1) No. Ou au moins pas dans les implémentations actuelles. Voir @lucasmo réponse à la preuve.
2) autant que je sache, non.
Hypothétiquement, il pourrait le faire. Cependant, ce qui prouve qu'un tableau n'est jamais modifié localement serait compliqué et relativement cher pour le JIT à effectuer. Si le tableau "échappe" à partir de la méthode qui a appelé
values()
, il devient de plus en plus complexe & plus cher.Les chances sont que cela (hypothétique) d'optimisation ne serait pas payer ... quand la moyenne sur tous les code Java.
L'autre problème est que cette (hypothétique) d'optimisation pourrait ouvrir des brèches de sécurité.
La chose intéressante est que la JLS ne semble pas préciser que la
values()
membre retourne un tableau copie. Le sens commun1 dit qu'il doit faire ... mais il n'est pas spécifié.1 - Il serait un énorme trou de sécurité si
values()
retourné partagé (mutable) tableau deenum
valeurs.