108 votes

Pourquoi local des variables non initialisées en Java?

Y avait-il une raison pourquoi les concepteurs de Java estimé que les variables locales ne doit pas être donné une valeur par défaut? Sérieusement, si les variables d'instance peut être donné une valeur par défaut, alors pourquoi ne pouvons-nous pas faire de même pour les variables locales?

Et il conduit également à des problèmes comme expliqué dans ce commentaire à un billet de blog...

64voto

Warrior Points 13394

Les variables locales sont déclarées pour la plupart de faire quelques calculs. Donc sa le programmeur de la décision pour définir la valeur de la variable et il ne devrait pas prendre une valeur par défaut. Si le programmeur, par erreur, n'a pas initialiser une variable locale et de prendre la valeur par défaut, le résultat pourrait être une valeur inattendue. Ainsi dans le cas de variables locales, le compilateur va demander au programmeur pour initialiser avec une valeur avant d'accéder à la variable d'éviter l'usage des valeurs indéfinies.

24voto

Rob Kennedy Points 107381

Le "problème" vous faites le lien semble décrire cette situation:

SomeObject so;
try {
  // Do some work here ...
  so = new SomeObject();
  so.DoUsefulThings();
} finally {
  so.CleanUp(); // Compiler error here
}

L'auteur de la plainte, c'est que le compilateur renâcle à la ligne dans l' finally section, affirmant qu' so peut être initialisée. Le commentaire puis mentionne une autre manière d'écrire le code, probablement quelque chose comme ceci:

// Do some work here ...
SomeObject so = new SomeObject();
try {
  so.DoUsefulThings();
} finally {
  so.CleanUp();
}

L'auteur n'est pas satisfait de cette solution, car le compilateur dit alors que le code "doit être à l'intérieur de l'essayer." Je suppose que cela signifie que le code peut lever une exception qui n'est pas traité plus. Je ne suis pas sûr. Ni la version de mon code gère toutes les exceptions, de sorte que rien de l'exception liée à la première version devrait fonctionner de la même dans le second.

De toute façon, cette deuxième version du code est correct façon de l'écrire. Dans la première version, le compilateur du message d'erreur était correcte. L' so variable peut être initialisée. En particulier, si l' SomeObject constructeur échoue, so ne sera pas initialisé, et si c'est une erreur de tentative d'appel d' so.CleanUp. Saisissez toujours l' try section après avoir acquis la ressource que l' finally section finalise.

L' try-finally bloc après l' so d'initialisation est là uniquement pour protéger l' SomeObject exemple, pour faire en sorte qu'il soit nettoyé n'importe quoi d'autre qui se passe. Si il y a d'autres choses qui ont besoin de courir, mais ils ne sont pas si l' SomeObject instance de la propriété attribués, alors qu'ils devraient aller dans un autre try-finally bloc, sans doute l'un qui encapsule celui que j'ai montré.

Nécessitant des variables à être attribuées manuellement avant l'utilisation ne conduisent pas à des problèmes réels. Il ne conduit qu'à un mineur de soucis, mais votre code sera mieux pour elle. Vous aurez variables de portée plus limitée, et try-finally blocs qui ne cherchent pas à protéger de trop.

Si les variables locales avaient des valeurs par défaut, puis so dans le premier exemple aurait été null. Qui ne s'est pas vraiment résolu quoi que ce soit. Au lieu d'obtenir une erreur de compilation dans l' finally bloc, vous avez une NullPointerException tapi là-bas qui pourrait cacher quelque autre exception peut se produire dans le "Faire un peu de travail ici" l'article du code. (Ou faire des exceptions en finally sections automatiquement de la chaîne à l'exception antérieure? Je ne me souviens pas. De même, vous auriez un extra exception dans le chemin du vrai.)

12voto

Electric Monk Points 1020

En outre, dans l'exemple ci-dessous, une exception peut avoir été jeté à l'intérieur de la SomeObject de construction, auquel cas la ' variable serait nulle et l'appel à un Nettoyage va lancer une exception NullPointerException

SomeObject so;
try {
  // Do some work here ...
  so = new SomeObject();
  so.DoUsefulThings();
} finally {
  so.CleanUp(); // Compiler error here
}

Ce que j'ai tendance à faire est ceci:

SomeObject so = null;
try {
  // Do some work here ...
  so = new SomeObject();
  so.DoUsefulThings();
} finally {
  if (so != null) {
     so.CleanUp(); // safe
  }
}

11voto

Adeel Ansari Points 24434

Notez que la dernière instance/variables de membre ne sont initialisées par défaut. Parce que ceux qui sont définitives et ne peuvent pas être modifiés dans le programme par la suite. C'est pour cette raison que Java n'est pas donner à tout défaut de la valeur pour eux et forcer le programmeur à initialiser.

D'autre part, les non-final variables de membre peut être modifié par toute personne ayant accès à ces variables. Donc le compilateur ne pas les laisser rester non initialisée, précisément, parce que ceux-ci peuvent être modifiés plus tard. Concernant les variables locales, la portée des variables locales est beaucoup plus étroite. Compilateur sait quand sa s'habituer. Par conséquent, forcer le programmeur à initialiser la variable de sens.

10voto

Bill K Points 32115

La réponse exacte à votre question, c'est parce que la méthode des variables sont instanciées par le simple ajout d'un numéro à le pointeur de pile. À zéro serait une étape supplémentaire. Pour les variables de classe sont mis en initialisé la mémoire sur le tas.

Pourquoi ne pas faire le pas supplémentaire? Prenez un peu de recul--Personne n'a mentionné que le "warning" dans ce cas c'est une Très Bonne Chose.

Vous ne devriez jamais initialiser vos variables à zéro ou à la valeur null lors de la première passe (lorsque vous êtes le premier codage). Soit l'affecter à la valeur réelle ou de ne pas l'attribuer à tous, parce que si vous n'avez pas java peut vous dire quand vous avez vraiment de la vis. Prenez Électrique du Moine réponse comme un grand exemple. Dans le premier cas, c'est en fait incroyablement utile qu'il vous dit que si le coup d'essayer() échoue parce que SomeObject le constructeur a déclenché une exception, alors vous vous retrouvez avec un NPE dans la enfin. Si le constructeur ne peut pas lancer une exception, il ne devrait pas être dans le coup d'essayer.

Cet avertissement est un super multi-chemin mauvais programmeur vérificateur qui m'a sauvé de faire des trucs stupides, car il vérifie chaque chemin d'accès et permet de s'assurer que si vous avez utilisé la variable dans le chemin alors que vous aviez à l'initialiser dans tous les chemins qui conduisent à elle. J'ai maintenant jamais explicitement initialiser des variables jusqu'à ce que je constate que c'est la bonne chose à faire.

En plus de cela, n'est-il pas préférable de dire explicitement "int taille=0" plutôt que "int size" et à faire de la prochaine programmeur allez comprendre que vous avez l'intention d'être de zéro?

Sur le revers de la médaille, je peux pas trouver une seule raison valable pour que le compilateur initialiser toutes les variables non initialisées à 0.

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