La idea detrás de las variables locales es que solo existen dentro del ámbito limitado para el que son necesarias. Como tal, debería haber pocas razones para la incertidumbre en cuanto al valor, o al menos, de dónde proviene ese valor. Podría imaginar muchos errores derivados de tener un valor predeterminado para las variables locales.
Por ejemplo, considere el siguiente código simple ... ( NB, supongamos con fines de demostración que a las variables locales se les asigna un valor predeterminado, como se especifica, si no se inicializan explícitamente )
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);
Cuando todo está dicho y hecho, asumiendo que el compilador asignó un valor predeterminado de '\ 0' a letterGrade , este código tal como está escrito funcionaría correctamente. Sin embargo, ¿qué pasa si olvidamos la declaración else?
Una ejecución de prueba de nuestro código puede resultar en lo siguiente
Enter grade
43
Your grade is
Este resultado, aunque era de esperar, seguramente no fue la intención del codificador. De hecho, probablemente en la gran mayoría de los casos (o al menos, en un número significativo de los mismos), el valor predeterminado no sería el valor deseado , por lo que en la gran mayoría de los casos el valor predeterminado resultaría en un error. Tiene más sentido forzar al codificador a asignar un valor inicial a una variable local antes de usarla, ya que el problema de depuración causado por olvidar el = 1
in for(int i = 1; i < 10; i++)
supera con creces la conveniencia de no tener que incluir el = 0
in for(int i; i < 10; i++)
.
Es cierto que los bloques try-catch-finalmente pueden volverse un poco desordenados (pero en realidad no es un catch-22 como parece sugerir la cita), cuando, por ejemplo, un objeto arroja una excepción marcada en su constructor, pero para uno razón u otra, se debe hacer algo con este objeto al final del bloque en finalmente. Un ejemplo perfecto de esto es cuando se trata de recursos, que deben cerrarse.
Una forma de manejar esto en el pasado podría ser así ...
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();
}
Sin embargo, a partir de Java 7, este bloque finalmente ya no es necesario usando try-with-resources, como ese.
try (Scanner s = new Scanner(new FileInputStream(new File("filename.txt")))) {
...
...
} catch(IOException e) {
System.out.println("different error message");
}
Dicho esto, (como sugiere el nombre) esto solo funciona con recursos.
Y aunque el ejemplo anterior es un poco asqueroso, esto quizás se refiera más a la forma en que se implementan try-catch-finalmente o estas clases que a las variables locales y cómo se implementan.
Es cierto que los campos se inicializan con un valor predeterminado, pero esto es un poco diferente. Cuando dice, por ejemplo, int[] arr = new int[10];
tan pronto como haya inicializado esta matriz, el objeto existe en la memoria en una ubicación determinada. Supongamos por un momento que no hay valores predeterminados, sino que el valor inicial es cualquier serie de 1 y 0 que esté en esa ubicación de memoria en ese momento. Esto podría llevar a un comportamiento no determinista en varios casos.
Supongamos que tenemos ...
int[] arr = new int[10];
if(arr[0] == 0)
System.out.println("Same.");
else
System.out.println("Not same.");
Sería perfectamente posible que Same.
se mostrara en una ejecución y Not same.
se mostrara en otra. El problema podría volverse aún más grave una vez que comience a hablar de variables de referencia.
String[] s = new String[5];
Según la definición, cada elemento de s debe apuntar a una cadena (o es nulo). Sin embargo, si el valor inicial es cualquier serie de 0 y 1 que ocurra en esta ubicación de memoria, no solo no hay garantía de que obtendrá los mismos resultados cada vez, sino que tampoco hay garantía de que el objeto s [0] apunte a (asumiendo que apunta a algo significativo) incluso es una Cadena (quizás sea un Conejo,: p )! Esta falta de preocupación por el tipo iría en contra de casi todo lo que hace Java Java. Entonces, si bien tener valores predeterminados para las variables locales podría verse como opcional en el mejor de los casos, tener valores predeterminados para las variables de ejemplo está más cerca de una necesidad .