L'idée derrière les variables locales est qu'elles n'existent que dans la portée limitée pour laquelle elles sont nécessaires. En tant que tel, il devrait y avoir peu de raisons d'incertitude quant à la valeur, ou du moins, à l'origine de cette valeur. Je pourrais imaginer de nombreuses erreurs résultant du fait d'avoir une valeur par défaut pour les variables locales.
Par exemple, considérons le code simple suivant ... ( NB supposons à des fins de démonstration que les variables locales se voient attribuer une valeur par défaut, comme spécifié, si elles ne sont pas explicitement initialisées )
System.out.println("Enter grade");
int grade = new Scanner(System.in).nextInt(); //I won't bother with exception handling here, to cut down on lines.
char letterGrade; //let us assume the default value for a char is '\0'
if (grade >= 90)
letterGrade = 'A';
else if (grade >= 80)
letterGrade = 'B';
else if (grade >= 70)
letterGrade = 'C';
else if (grade >= 60)
letterGrade = 'D';
else
letterGrade = 'F';
System.out.println("Your grade is " + letterGrade);
En fin de compte, en supposant que le compilateur attribue une valeur par défaut de '\ 0' à letterGrade , ce code tel qu'il est écrit fonctionnerait correctement. Cependant, que se passe-t-il si nous oublions la déclaration else?
Un test de notre code peut entraîner les résultats suivants
Enter grade
43
Your grade is
Ce résultat, bien que prévisible, n'était certainement pas l'intention du codeur. En effet, probablement dans la grande majorité des cas (ou du moins dans un nombre significatif de ceux-ci), la valeur par défaut ne serait pas la valeur souhaitée , donc dans la grande majorité des cas, la valeur par défaut entraînerait une erreur. Il est plus logique de forcer le codeur à attribuer une valeur initiale à une variable locale avant de l'utiliser, car le problème de débogage causé par l'oubli du = 1
in l' for(int i = 1; i < 10; i++)
emporte de loin sur la commodité de ne pas avoir à inclure le = 0
infor(int i; i < 10; i++)
.
Il est vrai que les blocs try-catch-finally pourraient devenir un peu désordonnés (mais ce n'est pas en fait un catch-22 comme la citation semble le suggérer), quand par exemple un objet lève une exception vérifiée dans son constructeur, mais pour une raison ou autre, quelque chose doit être fait à cet objet à la fin du bloc en enfin. Un exemple parfait de cela est lorsqu'il s'agit de ressources, qui doivent être fermées.
Une façon de gérer cela dans le passé pourrait être comme ça ...
Scanner s = null; //declared and initialized to null outside the block. This gives us the needed scope, and an initial value.
try {
s = new Scanner(new FileInputStream(new File("filename.txt")));
int someInt = s.nextInt();
} catch (InputMismatchException e) {
System.out.println("Some error message");
} catch (IOException e) {
System.out.println("different error message");
} finally {
if (s != null) //in case exception during initialization prevents assignment of new non-null value to s.
s.close();
}
Cependant, à partir de Java 7, ce bloc finally n'est plus nécessaire en utilisant try-with-resources, comme ça.
try (Scanner s = new Scanner(new FileInputStream(new File("filename.txt")))) {
...
...
} catch(IOException e) {
System.out.println("different error message");
}
Cela dit, (comme son nom l'indique), cela ne fonctionne qu'avec des ressources.
Et bien que le premier exemple soit un peu dégoûtant, cela en dit peut-être plus sur la façon dont try-catch-finally ou ces classes sont implémentées que sur les variables locales et la façon dont elles sont implémentées.
Il est vrai que les champs sont initialisés à une valeur par défaut, mais c'est un peu différent. Quand vous dites, par exemple,int[] arr = new int[10];
dès que vous avez initialisé ce tableau, l'objet existe en mémoire à un emplacement donné. Supposons un instant qu'il n'y a pas de valeurs par défaut, mais à la place la valeur initiale est n'importe quelle série de 1 et de 0 se trouvant dans cet emplacement de mémoire pour le moment. Cela pourrait conduire à un comportement non déterministe dans un certain nombre de cas.
Supposons que nous ayons ...
int[] arr = new int[10];
if(arr[0] == 0)
System.out.println("Same.");
else
System.out.println("Not same.");
Il serait parfaitement possible que cela Same.
puisse être affiché dans une course et Not same.
pourrait être affiché dans un autre. Le problème peut devenir encore plus grave une fois que vous commencez à parler des variables de référence.
String[] s = new String[5];
Selon la définition, chaque élément de s doit pointer vers une chaîne (ou est nul). Cependant, si la valeur initiale est n'importe quelle série de 0 et de 1 se produisant à cet emplacement de mémoire, non seulement il n'y a aucune garantie que vous obtiendrez les mêmes résultats à chaque fois, mais il n'y a pas non plus de garantie que l'objet s [0] pointe to (en supposant que cela indique quelque chose de significatif) est même une chaîne (peut-être que c'est un lapin,: p )! Ce manque de souci du type irait à l'encontre de pratiquement tout ce qui fait de Java Java. Ainsi, bien que les valeurs par défaut des variables locales puissent être considérées au mieux comme facultatives, avoir des valeurs par défaut pour les variables d'instance est plus proche d'une nécessité .