Question

La méthode suivante ne fonctionne pas car le bloc interne déclare une variable du même nom que celle du bloc externe. Apparemment, les variables appartiennent à la méthode ou à la classe dans laquelle elles sont déclarées, pas au bloc dans lequel elles sont déclarées. Je ne peux donc pas écrire un petit bloc temporaire pour le débogage qui pousse une variable de la portée externe dans ombre juste pour un moment:

void methodName() {
  int i = 7;
  for (int j = 0; j < 10; j++) {
    int i = j * 2;
  }
}

Presque toutes les langues à blocs que j'ai utilisées supportaient cette fonctionnalité, y compris les petites langues triviales pour lesquelles j'avais écrit des interprètes et des compilateurs à l'école. Perl peut le faire, de même que Scheme et même C. Même le PL / SQL le supporte!

Quelle est la raison de cette décision de conception pour Java?

Modifier: comme l’a souligné quelqu'un, Java a une portée de blocs. Quel est le nom du concept dont je parle? J'aimerais pouvoir me souvenir davantage de ces cours de conception de langage. :)

Était-ce utile?

La solution

Je pense que la raison en est que la plupart du temps, ce n'est pas intentionnel, c'est un défaut de programmation ou de logique.

dans un exemple aussi trivial que le vôtre, c’est évident, mais dans un gros bloc de code, il peut être moins évident de redéclarer une variable par accident.

ETA: il peut également être lié à la gestion des exceptions en Java. Je pensais qu'une partie de cette question avait été abordée dans une question concernant les raisons pour lesquelles les variables déclarées dans une section try n'étaient pas disponibles dans les champs de capture / de final.

Autres conseils

Eh bien, à proprement parler, Java a des déclarations de variables à portée de bloc; c'est donc une erreur:

void methodName() {
  for (int j = 0; j < 10; j++) {
    int i = j * 2;
  }
  System.out.println(i); // error
}

Parce que 'i' n'existe pas en dehors du bloc for.

Le problème est que Java ne vous permet pas de créer une variable portant le même nom qu'une autre variable déclarée dans un bloc externe de la même méthode. Comme d'autres l'ont déjà dit, cela aurait été fait pour prévenir les bugs difficiles à identifier.

Parce qu’il n’est pas rare que les écrivains fassent cela intentionnellement, puis tout bousiller en oubliant qu’il ya maintenant deux variables du même nom. Ils changent le nom de la variable interne, mais laissent le code qui utilise la variable, qui utilise maintenant de manière non intuitive la variable précédemment ombragée. Il en résulte un programme qui compile toujours, mais s’exécute de manière erronée.

De même, il n’est pas rare d’observer accidentellement des variables et de modifier le comportement du programme. Ombrer inconsciemment une variable existante peut changer le programme aussi facilement que de ne pas ombrager une variable, comme indiqué plus haut.

Il y a si peu d'avantages à autoriser cet ombrage qu'il a été jugé trop dangereux. Sérieusement, appelez simplement votre nouvelle variable et le problème disparaîtra.

Cela conduit à des bugs difficiles à repérer, je suppose. C'est similaire en C #.

Pascal ne le supporte pas, car vous devez déclarer des variables au-dessus du corps de la fonction.

L'hypothèse sous-jacente à cette question est fausse.

Java a une portée au niveau du bloc. Mais il a également une hiérarchie de portée, raison pour laquelle vous pouvez référencer i dans la boucle pour , mais pas j à l'extérieur de la boucle for .

public void methodName() {
  int i = 7;
  for (int j = 0; j < 10; j++) {
    i = j * 2;
  }

  //this would cause a compilation error!
  j++;
}

Je ne peux pas comprendre pourquoi vous voudriez que le scoping se comporte autrement. Il serait impossible de déterminer le i auquel vous faisiez référence dans la boucle for, et je parierais que les chances sont 99,999% du temps où vous souhaitez faire référence au i dans la méthode.

autre raison: si ce type de déclaration de variable était autorisé, les utilisateurs voudraient (si nécessaire) un moyen d'accéder aux variables de bloc externes. peut être quelque chose comme "externe" le mot clé serait ajouté:

void methodName() {
    int i = 7;
    for (int j = 0; j < 10; j++) {
        int i = outer.i * 2;
        if(i > 10) {
            int i = outer.outer.i * 2 + outer.i;
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top