Идея, лежащая в основе локальных переменных, заключается в том, что они существуют только в ограниченном объеме, для которого они нужны. Таким образом, должно быть мало причин для неопределенности в отношении значения или, по крайней мере, откуда оно берется. Я мог бы представить множество ошибок, возникающих из-за того, что для локальных переменных было установлено значение по умолчанию.
Например, рассмотрим следующий простой код ... ( N.B. Допустим для демонстрации, что локальным переменным присваивается значение по умолчанию, как указано, если не инициализировано явно )
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);
Когда все сказано и сделано, при условии, что компилятору присвоено значение по умолчанию '\ 0' для letterGrade , этот написанный код будет работать правильно. Однако что, если мы забыли выражение else?
Тестовый запуск нашего кода может привести к следующему
Enter grade
43
Your grade is
Этот результат, хотя и следовало ожидать, несомненно, не был целью кодера. Действительно, вероятно, в подавляющем большинстве случаев (или, по крайней мере, в значительном их числе) значением по умолчанию не будет значение требуемый , поэтому в подавляющем большинстве случаев значение по умолчанию будет иметь результатом в ошибке. Имеет больше смысла заставлять кодера присваивать начальное значение локальной переменной перед ее использованием, поскольку горе отладки, вызванное забыванием = 1
в for(int i = 1; i < 10; i++)
, значительно перевешивает удобство отсутствия необходимости включать = 0
в for(int i; i < 10; i++)
.
Это правда, что блоки try-catch-finally могут немного запутаться (но на самом деле это не catch-22, как кажется из цитаты), когда, например, объект выдает проверенное исключение в своем конструкторе, все же по той или иной причине что-то должно быть сделано с этим объектом в конце блока в finally. Прекрасным примером этого является работа с ресурсами, которые должны быть закрыты.
Один из способов справиться с этим в прошлом мог бы быть таким ...
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();
}
Однако, начиная с Java 7, этот блок finally больше не требуется при использовании try-with-resources, например так.
try (Scanner s = new Scanner(new FileInputStream(new File("filename.txt")))) {
...
...
} catch(IOException e) {
System.out.println("different error message");
}
Тем не менее, (как следует из названия) это работает только с ресурсами.
И хотя предыдущий пример немного отвратителен, возможно, это говорит скорее о том, как try-catch-finally или эти классы реализованы, чем о локальных переменных и о том, как они реализованы.
Это правда, что поля инициализируются значением по умолчанию, но это немного отличается. Когда вы говорите, например, int[] arr = new int[10];
, как только вы инициализируете этот массив, объект существует в памяти в данном месте. Давайте на минутку предположим, что значений по умолчанию нет, но вместо этого начальное значение - это любая серия из 1 и 0, которая в данный момент находится в этой ячейке памяти. Это может привести к недетерминированному поведению в ряде случаев.
Предположим, у нас есть ...
int[] arr = new int[10];
if(arr[0] == 0)
System.out.println("Same.");
else
System.out.println("Not same.");
Вполне возможно, что Same.
может отображаться в одном прогоне, а Not same.
может отображаться в другом. Проблема может стать еще более серьезной, если вы начнете говорить о ссылочных переменных.
String[] s = new String[5];
Согласно определению, каждый элемент s должен указывать на строку (или равен нулю). Однако, если начальное значение соответствует серии 0 и 1, происходящей в этой области памяти, не только нет гарантии, что вы будете получать одинаковые результаты каждый раз, но также нет гарантии, что объект s [0] указывает чтобы (предполагая, что это указывает на что-то значимое), даже - это Строка (возможно, это Кролик, : p )! Это отсутствие заботы о типе бросило бы вызов почти всему, что делает Java Java. Таким образом, хотя значения по умолчанию для локальных переменных в лучшем случае могут рассматриваться как необязательные, наличие значений по умолчанию для переменных экземпляра ближе к необходимость .