una tipos que programacion ejemplos declarar declaraciones declaracion datos constante java syntax language-design

java - que - tipos de declaracion de variables



¿Por qué Java no tiene declaraciones de variables de ámbito de bloque? (6)

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 solo por un momento:

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

Casi todos los lenguajes de bloque que he usado alguna vez lo soportan, incluidos pequeños lenguajes triviales para los 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. :)


Bueno, estrictamente hablando, Java 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 declarada 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.


Creo que el razonamiento 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.


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

Pascal no lo admite, ya que debe declarar las variables por encima del cuerpo de la función.


La suposición subyacente en esta pregunta es incorrecta.

Java tiene un alcance de nivel de bloque. Pero también tiene una jerarquía de alcance, por lo que puede hacer referencia a i dentro del bucle for , pero no a 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ías que el alcance se comportara de otra manera. Sería imposible determinar a qué se refiere en el ciclo for, y apostaría a que el 99.999% del tiempo desea referirse a la i dentro del método.


Porque no es raro que los escritores lo hagan intencionalmente y luego lo arruinen 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.

Del mismo modo, 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á.


otra razón: si se permitiera este tipo de declaración de variables, la gente querría (¿necesitaría?) una forma de acceder a las variables externas del bloque. 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; } } }