2008-09-26 14 views
10

El siguiente método no funciona porque el bloque interno declara una variable del mismo nombre que una en el bloque externo. Aparentemente, las variables pertenecen al método o clase en la que se declaran, no al bloque en el que se declaran, por lo que no puedo escribir un pequeño bloque temporal corto para la depuración que sucede al empujar una variable en el ámbito externo hacia sombra sólo por un momento:¿Por qué Java no tiene declaraciones de variables de ámbito de bloque?

void methodName() { 
    int i = 7; 
    for (int j = 0; j < 10; j++) { 
    int i = j * 2; 
    } 
} 

casi todos los idiomas del bloque de ámbito que he utilizado alguna vez a favor de este, incluyendo pequeñas lenguas triviales que escribí intérpretes y compiladores en la escuela. Perl puede hacer esto, al igual que Scheme, e incluso C. ¡Incluso PL/SQL lo admite!

¿Cuál es la razón de esta decisión de diseño para Java?

Editar: como alguien señaló, Java tiene un alcance de bloque. ¿Cuál es el nombre para el concepto que estoy preguntando? Ojalá pudiera recordar más de esas clases de diseño de lenguaje. :)

Respuesta

12

Creo que la razón es que la mayoría de las veces, eso no es intencional, es una falla de programación o lógica.

en un ejemplo tan trivial como el suyo, es obvio, pero en un gran bloque de código, redeclar accidentalmente una variable puede no ser obvio.

ETA: también podría estar relacionado con el manejo de excepciones en java. pensé que parte de esta pregunta se discutió en una pregunta relacionada con por qué las variables declaradas en una sección de prueba no estaban disponibles en los ámbitos catch/finally.

+0

La primera vez que vi esto fue en Exception-handling. Ahí no pensé nada de eso; Simplemente asumí que la implementación lo excluía por alguna razón interna. No fue hasta que noté que afectaba a los bloques simples que realmente comencé a preguntarme "¿por qué?" – skiphoppy

10

Esto conduce a errores que son difíciles de detectar, supongo. Es similar en C#.

Pascal no es compatible con esto, ya que debe declarar las variables por encima del cuerpo de la función.

19

Porque no es raro que los escritores lo hagan intencionadamente y luego lo arruinan por completo al olvidar que ahora hay dos variables con el mismo nombre. Cambian el nombre de la variable interna, pero dejan el código que usa la variable, que ahora usa de forma poco intencionada la variable sombreada previamente. Esto da como resultado un programa que aún compila, pero ejecuta buggily.

De manera similar, no es raro omitir las variables por accidente y cambiar el comportamiento del programa. Sin saberlo, sombrear una variable existente puede cambiar el programa tan fácilmente como descifrar una variable como mencioné anteriormente.

Hay tan poco beneficio en permitir este sombreado que lo descartaron como demasiado peligroso. En serio, simplemente llame a su nueva variable y el problema desaparecerá.

+2

Iría más lejos para decir que NO hay ninguna razón para hacer esto en absoluto. No hay nada que puedas hacer con variables ocultas que no puedes hacer sin ellas. – JavadocMD

+2

La única vez que me gustan es en argumentos constructor, entonces puedo hacer "this.foo = foo". El nombre que se destruye por el bien de los constructores es feo, feo, feo. "_foo", "foo_", bla. –

24

Bueno, estrictamente hablando, Java tiene tiene declaraciones de variables de ámbito de bloque; entonces este es un error:

void methodName() { 
    for (int j = 0; j < 10; j++) { 
    int i = j * 2; 
    } 
    System.out.println(i); // error 
} 

Porque 'i' no existe fuera del bloque for.

El problema es que Java no le permite crear una variable con el mismo nombre de otra variable que se declaró en un bloque externo del mismo método. Como han dicho otras personas, supuestamente esto se hizo para evitar errores que son difíciles de identificar.

1

La suposición subyacente en esta pregunta es incorrecta.

Java tiene tienen alcance de nivel de bloque. Pero también tiene una jerarquía de alcance, por lo que puede hacer referencia al i dentro del bucle for, pero no al j fuera del bucle for.

public void methodName() { 
    int i = 7; 
    for (int j = 0; j < 10; j++) { 
    i = j * 2; 
    } 

    //this would cause a compilation error! 
    j++; 
} 

No puedo entender por qué querría que el alcance se comportara de otra manera. Sería imposible determinar a qué i se refería dentro del bucle for, y apostaría que el 99.999% de las veces desea referirse al i dentro del método.

+0

Quiero referirme a la i dentro del método. Así es como C, Perl y Scheme funcionan. Entonces, ¿por qué eso hace que sea imposible determinar cuál yo quiero? – skiphoppy

0

otra razón: si se permitiera este tipo de declaración de variable, la gente querría (¿necesitaría?) Una forma de acceder a las variables de bloque externas. puede ser algo así como la palabra clave "externa" se agregaría:

void methodName() { 
    int i = 7; 
    for (int j = 0; j < 10; j++) { 
     int i = outer.i * 2; 
     if(i > 10) { 
      int i = outer.outer.i * 2 + outer.i; 
     } 
    } 
} 
Cuestiones relacionadas