Pourquoi les variables locales, y compris les primitives, doivent-elles toujours être initialisées en Java? Pourquoi la même chose ne s'applique-t-elle pas dans le cas de variables d'instance?
Il y avait une question à propos de cela très récemment pour C # ... - lisez les réponses ici aussi, car c'est fondamentalement la même chose. Vous pourriez également trouver le récent article de blog d'Eric Lippert intéressant; c'est du moins le même secteur, même si sa portée est quelque peu différente.
Fondamentalement, demander à une variable de se voir attribuer une valeur avant de la lire est une bonne chose. Cela signifie que vous ne lirez pas accidentellement quelque chose que vous n'aviez pas l'intention de faire. Oui, les variables peuvent avoir des valeurs par défaut - mais ne vaut-il pas mieux que le compilateur puisse attraper votre bogue à la place, s'il peut prouver que vous essayez de lire quelque chose qui n'a peut-être pas encore été attribué? Si vous souhaitez attribuer une valeur par défaut à une variable locale, vous pouvez toujours l'affecter explicitement.
Cela convient pour les variables locales, mais par exemple pour les variables statiques, le compilateur n'a aucun moyen de connaître l'ordre dans lequel les méthodes seront appelées. Une propriété "setter" sera-t-elle appelée avant le "getter"? Il n'a aucun moyen de le savoir, il n'a donc aucun moyen de vous alerter du danger. C'est pourquoi les valeurs par défaut sont utilisées pour les variables d'instance/statiques - vous obtiendrez au moins une valeur connue (0, false, null, etc.) au lieu de simplement "ce qui s'est passé en mémoire à ce moment-là". (Cela élimine également le problème de sécurité potentiel lié à la lecture de données sensibles qui n’avait pas été explicitement effacé.)
En Java, les variables de classe et d'instance prennent une valeur par défaut (null, 0, false) si elles ne sont pas initialisées manuellement. Cependant, les variables locales n'ont pas de valeur par défaut. À moins qu'une valeur locale ait été assignée à une valeur, le compilateur refusera de compiler le code qui la lit. IMHO, cela mène à la conclusion que l'initialisation d'une variable locale avec une valeur par défaut (telle que null, pouvant conduire à une exception NullPointerException ultérieurement) lorsqu'elle est déclarée est en fait une mauvaise chose. Prenons l'exemple suivant:
Object o;
if (<some boolean condition>)
o = <some value>;
else
o = <some other value>;
System.out.println(o);
Une initialisation de o
avec null est totalement inutile, car le compilateur Java vérifie, au moment de la compilation, que tout chemin de code initialise o
(avec la valeur null ou une valeur non nulle) avant la lecture de la variable. Cela signifie que le compilateur refusera de compiler la ligne System.out.println(o);
si vous souhaitez commenter l'une des deux initialisations de la variable o
dans le fragment de code ci-dessus.
Ceci est valable pour Java, et peut-être uniquement pour Java. Je ne connais pas de langage comme C #. En bon vieux C (et peut-être C++), il est toujours recommandé de toujours initialiser les variables lors de leur déclaration, autant que je sache. Ces langages de programmation "à l'ancienne" pourraient être la raison pour laquelle la recommandation d'initialiser toujours les variables apparaît dans les livres et les discussions sur les langages modernes comme Java, où la compilation indique si une variable a été initialisée ou non.
Eh bien, dans le cas de variable locale, il est clair ce que cela signifie "avant" puisque le programme s'écoule entre la déclaration (dans la méthode) et la référence est séquentielle. Dans le cas de champs déclarés en dehors de la méthode, le compilateur ne sait jamais quel code sera utilisé, il ne peut donc pas générer d'erreur car une autre méthode peut éventuellement initialiser le champ avant son utilisation.
Pas tout à fait vrai. Les variables locales ne doivent être initialisées que si elles sont référencées. Une variable locale peut être laissée non initialisée si elle n'est jamais référencée. Par exemple:
int x; // Valid
int y;
println("y=" + y); // Not valid since y's value has never been assigned
Les variables locales et les primitives doivent être initialisées avant utilisation car vous savez à quoi vous attendre des valeurs. Historiquement, quand une nouvelle variable était créée, elle contenait des valeurs aléatoires de la mémoire [et on ne pouvait pas prédire la valeur]. Java le requiert également, car il empêche la présence de variables orphelines.
Il est nécessaire d’initialiser les variables locales (uniquement lorsque nous les utilisons) car elles n’obtiennent aucune valeur par défaut comme les variables d’instance.
Et comme règle de base, nous devrions toujours initialiser toute variable avant de l’utiliser. Sinon, cela pourrait entraîner une erreur telle que nullPointer, etc.
Maintenant, pourquoi les variables locales ne reçoivent-elles pas la valeur par défaut? La raison en est que les variables locales résident sur la pile et ne sont visibles que dans le contexte de la méthode locale, contrairement aux variables d'instance qui résident sur le tas et ont une portée tout au long du programme.
Ainsi, lorsque la pile mettra fin à la méthode locale, la valeur de la méthode locale sera également détruite, donc: .__] false) comme les variables d'instance
En passant par la définition de variable locale dans laquelle état, une variable locale est déclarée dans une fonction ou est passée en argument dans une fonction. Si vous n'initialisez pas une variable locale, vous rencontrerez un problème de gestion des exceptions car le compilateur ne sera pas en mesure de comprendre la valeur de la variable.
En pratique, toutes les variables doivent être initialisées avant de les utiliser.
Je ne peux pas penser à un moment où vous voudriez utiliser une variable avant de définir sa valeur (sauf si vous la comparez à null).