Die Idee hinter lokalen Variablen ist, dass sie nur innerhalb des begrenzten Bereichs existieren, für den sie benötigt werden. Daher sollte es wenig Grund zur Unsicherheit hinsichtlich des Werts geben oder zumindest, woher dieser Wert stammt. Ich könnte mir viele Fehler vorstellen, die sich aus einem Standardwert für lokale Variablen ergeben.
Betrachten Sie zum Beispiel den folgenden einfachen Code ... ( Hinweis: Nehmen wir zu Demonstrationszwecken an, dass lokalen Variablen ein Standardwert zugewiesen wird, wie angegeben, wenn er nicht explizit initialisiert wird. )
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);
Wenn alles gesagt und getan ist, würde dieser geschriebene Code ordnungsgemäß funktionieren , vorausgesetzt, der Compiler hat letterGrade den Standardwert '\ 0' zugewiesen . Was aber, wenn wir die else-Anweisung vergessen haben?
Ein Testlauf unseres Codes kann Folgendes bewirken
Enter grade
43
Your grade is
Dieses Ergebnis war zwar zu erwarten, aber sicherlich nicht die Absicht des Programmierers. In der Tat würde der Standardwert wahrscheinlich in den allermeisten Fällen (oder zumindest in einer signifikanten Anzahl davon) nicht der gewünschte Wert sein, sodass der Standardwert in den allermeisten Fällen zu Fehlern führen würde. Es ist sinnvoller, den Codierer zu zwingen, einer lokalen Variablen vor der Verwendung einen Anfangswert zuzuweisen, da der durch das Vergessen des = 1In verursachte Fehler beim Debuggen for(int i = 1; i < 10; i++)die Bequemlichkeit überwiegt, das In nicht einschließen = 0zu müssen for(int i; i < 10; i++).
Es ist wahr, dass Try-Catch-finally-Blöcke etwas chaotisch werden können (aber es ist eigentlich kein Catch-22, wie das Zitat zu vermuten scheint), wenn beispielsweise ein Objekt eine geprüfte Ausnahme in seinem Konstruktor auslöst, jedoch für eine Grund oder eine andere, muss etwas mit diesem Objekt am Ende des Blocks in endlich getan werden. Ein perfektes Beispiel hierfür ist der Umgang mit Ressourcen, die geschlossen werden müssen.
Eine Möglichkeit, in der Vergangenheit damit umzugehen, könnte so sein ...
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();
}
Ab Java 7 ist dieser endgültige Block jedoch nicht mehr erforderlich, wenn Sie versuchen, Ressourcen zu verwenden.
try (Scanner s = new Scanner(new FileInputStream(new File("filename.txt")))) {
...
...
} catch(IOException e) {
System.out.println("different error message");
}
Das heißt, (wie der Name schon sagt) funktioniert dies nur mit Ressourcen.
Und während das erstere Beispiel ein bisschen glücklich ist, spricht dies vielleicht mehr für die Art und Weise, wie try-catch-finally oder diese Klassen implementiert werden, als für lokale Variablen und wie sie implementiert werden.
Es ist wahr, dass Felder mit einem Standardwert initialisiert werden, aber das ist etwas anders. Wenn Sie beispielsweise sagen, int[] arr = new int[10];sobald Sie dieses Array initialisiert haben, befindet sich das Objekt an einem bestimmten Ort im Speicher. Nehmen wir für einen Moment an, dass es keine Standardwerte gibt, sondern der Anfangswert eine beliebige Reihe von Einsen und Nullen ist, die sich gerade an diesem Speicherort befindet. Dies könnte in einigen Fällen zu nicht deterministischem Verhalten führen.
Angenommen, wir haben ...
int[] arr = new int[10];
if(arr[0] == 0)
System.out.println("Same.");
else
System.out.println("Not same.");
Es wäre durchaus möglich, dass Same.dies in einem Lauf und in einem anderen Lauf Not same.angezeigt wird. Das Problem könnte noch schwerwiegender werden, wenn Sie anfangen, Referenzvariablen zu sprechen.
String[] s = new String[5];
Gemäß der Definition sollte jedes Element von s auf einen String zeigen (oder ist null). Wenn der Anfangswert jedoch eine beliebige Reihe von Nullen und Einsen ist, die an diesem Speicherort auftreten, gibt es nicht nur keine Garantie, dass Sie jedes Mal die gleichen Ergebnisse erhalten, sondern auch keine Garantie dafür, dass das Objekt s [0] zeigt zu (vorausgesetzt , es weist auf etwas Sinnvolles) selbst ist ein String (vielleicht ist es ein Kaninchen, : p )! Dieser Mangel an Sorge um den Typ würde so ziemlich allem widersprechen, was Java Java ausmacht. Während Standardwerte für lokale Variablen bestenfalls als optional angesehen werden können, sind Standardwerte für beispielsweise Variablen einer Notwendigkeit näher .