32 votes

Pourquoi la variable locale d'une boucle for améliorée doit-elle être locale?

Selon le Java Language Specification, § 14.14.2, la variable de l'amélioration de l' for , la boucle doit être locale à la boucle. En d'autres termes, cette compile:

for (State state : State.values()) {
    // do something for each state
}

mais ce n'est pas:

State state;
for (state: State.values()) {
    // do something for each state
}

Le JLS ne donne aucune justification de cette langue est un choix de conception. Je peux voir pourquoi le nom du type doit être présent si la variable locale est modifié par final ou par une annotation, mais je ne comprends pas pourquoi un nu nom d'une variable déclarée ailleurs n'est pas autorisé. Quelqu'un aurait-il tout de comprendre pourquoi cette restriction a été imposée?

MODIFIER

Plusieurs réponses semblent être ce qui suggère que ce qui se passe en dehors de la boucle est la raison pour la conception de la langue cette façon. Peut-être un examen approfondi de la JLS affirme une volonté de clarifier la raison pour laquelle je ne trouve pas convaincantes. Considérer cette boucle, où State est un enum:

for (State state : State.values()) {
    // ...
}

State.values() est un tableau, donc en fonction de la JLS, la boucle est fonctionnellement identique à:

State[] a = State.values();
for (int i = 0; i < a.length; i++) {
    State state = a[i];
    // ...
}

Maintenant clairement cette dernière boucle, pourrait avoir été écrit:

State state;
State[] a = State.values();
for (int i = 0; i < a.length; i++) {
    state = a[i];
    // ...
}

Conceptuellement, cette dernière (parfaitement légal) de la boucle pourrait avoir été utilisé comme l'équivalent fonctionnel de la deuxième renforcée for boucle ci-dessus (celle qui ne compile pas).

De même, si stateList est Iterable<State> (pas un tableau), cette boucle:

for (State state : stateList) {
    // ...
}

est fonctionnellement identique à:

for (Iterator<State> iterator = stateList.iterator(); iterator.hasNext(); ) {
    State state = iterator.next();
    // ...
}

Comme avant, cette dernière boucle pourrait avoir été écrit:

State state;
for (Iterator<State> iterator = stateList.iterator(); iterator.hasNext(); ) {
    state = iterator.next();
    // ...
}

Encore une fois, ce pourrait avoir été utilisé comme l'équivalent fonctionnel de l' (illégaux):

State state;
for (state : stateList) {
    // ...
}

Dans chaque cas, lorsque la boucle, la valeur de state est parfaitement bien défini (si, peut-être, inutile). Aussi, tout comme la boucle régulière, renforcement de l' for boucle à l'aide d'un nu nom de la variable qui n'a pas été définie (par exemple, la ligne State state; était manquant ou hors de portée) pourrait être pris au moment de la compilation. Donc, à partir d'un langage de conception de point de vue, quel est le problème? Pourquoi la langue des designers hors la loi cette construction?

11voto

Adithya Surampudi Points 2529

Regardez comment la boucle for-each interne fonctionne, voir Comment le Java pour chaque boucle de travail?

for(Iterator<String> i = someList.iterator(); i.hasNext(); ) {
String item = i.next();
System.out.println(item);
}

Chaque fois qu'il déclare la variable Chaîne de caractères de l'élément. Donc dans votre cas sa fait essentiellement

State state;
\\and inside
State state = i.next();

qui, évidemment, ne fonctionnent pas. Maintenant à l'intérieur de la mise en œuvre, ils pourraient plutôt faire

item = i.next();

mais alors vous devez toujours définir qui point à l'extérieur pour chaque, ce qui serait une douleur à la majorité du temps.

9voto

havexz Points 6707

Un avantage / justification est que les variables locales ne polluent pas votre code. Permettez-moi de donner un exemple de boucle normale (c'est juste pour l'analogie pas exacte, donc pas d'utilisation d'itérateur):

 int i;
for(i=0;i<10;i++)
  do...something

int j;
for(j=0; i<10; j++)
  do...something
 

Maintenant, dans le code ci-dessus, si vous regardez attentivement, vous trouverez un bogue potentiel. i a été utilisé par erreur dans une boucle qui itère sur j .

Les boucles améliorées tentent donc de jouer en toute sécurité en créant les variables localement, ce qui vous permet d'éviter le problème ci-dessus.

7voto

Bill K Points 32115

Beaucoup de décisions en Java sont plus basés sur le concept de " pourquoi "ne" vous supprimer x. Pourquoi sur la terre permettre à votre code d'être confondu par le déplacement de la portée à l'extérieur de la boucle? Si vous avez vraiment besoin d'avoir accès au dernier élément après il y sont plus propres moyens.

Je suppose que certains pourraient faire valoir d'une manière ou d'une autre qu'à la protection des programmeurs d'eux-mêmes, je la regarde plus comme Java me protège contre des gens qui aiment prendre avantage de ce genre de choses.

Ce n'est pas vraiment un grand passe-temps de la langue, c'est une grande équipe de développement de la langue où le point est de le rendre aussi facile que possible pour le gars à côté de comprendre votre code.

Par exemple, j'ai vu dans un commentaire ci-dessus que beaucoup de gens sortir d'une boucle for à un certain point, avec une valeur. Comment clair, c'est que lorsque vous numérisez à l'aide de code en essayant de trouver un bug? Ce sont des gens en utilisant des trucs comme ce que je veux vraiment être protégé contre, pas moi.

Si vous souhaitez exécuter un code en milieu de boucle, le mettre dans une méthode et de l'appeler à partir de l'intérieur de la boucle.

Le manque de mignon de trucs me fait souvent réfléchir de mon code et de travailler un peu plus difficile-mais les résultats sont toujours plus lisible et maintenable.

Si vous êtes juste un seul programmeur (Pas sur une équipe) je vous le déconseille Java, Il ne fait pas de trucs et vous ne verrez pas cool d'année en année des mises à jour--et il est assez lent pour le programme (Il se déplace beaucoup de temps attraper et la correction des bogues dans le temps passé codage, frustrant pour les gens avec des règles strictes (l'Un des plus grands avantages de la langue de l'OMI)

Si vous voulez quelque chose de javaish essayer Scala à la place. Si vous êtes "Obligés" de l'apprendre, car d'une classe de la décision, alors vous pourriez vouloir essayer de l'apprécier, de la "team" point de vue et avec l'état d'esprit que vous ne serez pas obligés de l'utiliser dans l'avenir.

5voto

Vlad Points 7354

Ils auraient voulu supprimer une possible différence de sémantique entre le simple et le renforcement de la pour les.

Si vous avez, disons, une boucle for:

int i;
for (i=0; i<4; i++)
    ;

ensuite, si vous laissez la boucle s'exécuter normalement, vous obtenez ce que l' i==4 après la boucle, ce qui n'est pas valide pour la variable d'itération.

Quelle est, alors, si vous pourriez avoir:

int i;
for (i : myArray)
    ;

Je suppose qu'à partir d'un point de vue de la mise en œuvre, il serait plus simple si, à la fin de l' i était égal au dernier élément du tableau. Mais doit-il se comporter comme ça ou faut-il une certaine valeur non valide, et si oui, quel pourrait-il être? Que faire si vous sortir de la dernière itération?

Une autre possibilité est qu'il devient de plus en plus clair que cette boucle et qu'est ce que le type de l'élément de la collection est. En revanche, le simple est un "héritage" de construire dans un certain sens, de sorte qu'ils ne pouvaient pas avoir appliqué une logique similaire sans "casser" ou de limiter sa flexibilité.

Je suis évidemment à spéculer, et il pourrait avoir juste été un hasard est un choix de conception.

3voto

Eng.Fouad Points 44085

Peut-être parce que de cette façon, cela garantit que state sera vide et n'a pas de valeur initiale qui lui est assignée.

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