una simbolica las instancia inicializar inicializacion donde declaran declaracion declara constantes constante como java variables initialization

simbolica - ¿Por qué las variables locales no se inicializan en Java?



inicializar char java (13)

¿Hubo alguna razón por la cual los diseñadores de Java consideraran que las variables locales no deberían tener un valor predeterminado? En serio, si a las variables de instancia se les puede asignar un valor predeterminado, ¿por qué no podemos hacer lo mismo con las variables locales?

Y también lleva a problemas como se explica en este comentario a una publicación de blog :

Bueno, esta regla es muy frustrante cuando se trata de cerrar un recurso en un bloque finally. Si instancia el recurso dentro de un intento, pero trato de cerrarlo dentro del final, obtengo este error. Si muevo la instanciación fuera del intento, aparece otro error que indica que debe estar dentro de un intento.

Muy frustrante.


(Puede parecer extraño publicar una nueva respuesta mucho tiempo después de la pregunta, pero apareció un duplicate ).

Para mí, la razón se reduce a esto: el propósito de las variables locales es diferente al propósito de las variables de instancia. Las variables locales están allí para ser utilizadas como parte de un cálculo; las variables de instancia están ahí para contener el estado. Si usa una variable local sin asignarle un valor, es casi seguro que es un error de lógica.

Dicho esto, podría retroceder totalmente y exigir que las variables de instancia siempre se inicialicen explícitamente; el error ocurriría en cualquier constructor donde el resultado permita una variable de instancia no inicializada (por ejemplo, no inicializada en la declaración y no en el constructor). Pero esa no es la decisión Gosling, et. al., tomó en los años 90, así que aquí estamos. (Y no estoy diciendo que hicieron la llamada incorrecta).

Sin embargo, no pude estar detrás de las variables locales predeterminadas. Sí, no debemos confiar en los compiladores para verificar nuestra lógica, y otra no, pero sigue siendo útil cuando el compilador saca uno. :-)


Además, en el siguiente ejemplo, puede haberse lanzado una excepción dentro de la construcción de SomeObject, en cuyo caso la variable ''so'' sería nula y la llamada a CleanUp generará una excepción NullPointerException

SomeObject so; try { // Do some work here ... so = new SomeObject(); so.DoUsefulThings(); } finally { so.CleanUp(); // Compiler error here }

Lo que tiendo a hacer es esto:

SomeObject so = null; try { // Do some work here ... so = new SomeObject(); so.DoUsefulThings(); } finally { if (so != null) { so.CleanUp(); // safe } }


Creo que el objetivo principal era mantener la similitud con C / C ++. Sin embargo, el compilador detecta y le advierte sobre el uso de variables no inicializadas que reducirán el problema a un punto mínimo. Desde la perspectiva del rendimiento, es un poco más rápido permitirle declarar variables no inicializadas, ya que el compilador no tendrá que escribir una instrucción de asignación, incluso si sobrescribe el valor de la variable en la siguiente declaración.


Eclipse incluso te da advertencias de variables no inicializadas, por lo que se vuelve bastante obvio de todos modos. Personalmente, creo que es bueno que este sea el comportamiento predeterminado, de lo contrario su aplicación puede usar valores inesperados, y en lugar de que el compilador arroje un error, no hará nada (pero quizás advierta) y luego se rascará. su cabeza de por qué ciertas cosas no se comportan del modo que deberían.


Es más eficiente no inicializar las variables y, en el caso de las variables locales, es seguro hacerlo, ya que el compilador puede rastrear la inicialización.

En los casos en que necesite que se inicialice una variable, siempre puede hacerlo usted mismo, por lo que no es un problema.


La respuesta es que las variables de instancia se pueden inicializar en el constructor de la clase o en cualquier método de clase, pero en el caso de las variables locales, una vez que se define lo que sea en el método, permanece para siempre en la clase.


La respuesta real a su pregunta es porque las variables del método se instancian simplemente agregando un número al puntero de la pila. Ponerlos a cero sería un paso adicional. Para las variables de clase, se colocan en la memoria inicializada en el montón.

¿Por qué no dar el paso extra? Dar un paso atrás - Nadie mencionó que la "advertencia" en este caso es algo muy bueno.

Nunca debe inicializar su variable a cero o nulo en la primera pasada (cuando la está codificando por primera vez). Ya sea que lo asigne al valor real o no lo asigne en absoluto, si no lo hace, entonces java puede decirle cuándo realmente se equivoca. Tome la respuesta de Electric Monk como un gran ejemplo. En el primer caso, es increíblemente útil que te esté diciendo que si try () falla porque el constructor de SomeObject lanzó una excepción, entonces terminarías con un NPE en el final. Si el constructor no puede lanzar una excepción, no debería estar en el intento.

Esta advertencia es una impresionante corrector de programadores de múltiples rutas que me ha evitado hacer cosas estúpidas ya que comprueba todas las rutas y se asegura de que si usabas la variable en alguna ruta, entonces tuviste que inicializarla en cada ruta que conduzca a ella. . Ahora nunca inicializo explícitamente variables hasta que determino que es lo correcto.

Además de eso, ¿no es mejor decir explícitamente "int size = 0" en lugar de "int size" y hacer que el próximo programador averigüe que usted tiene la intención de que sea cero?

Por otro lado, no puedo encontrar una razón válida para que el compilador inicialice todas las variables sin inicializar a 0.


La variable de instancia tendrá valores predeterminados, pero las variables locales no podrían tener valores predeterminados. Dado que las variables locales se basan básicamente en métodos / comportamiento, su objetivo principal es realizar algunas operaciones o cálculos. Por lo tanto, no es una buena idea establecer valores predeterminados para las variables locales. De lo contrario, es muy difícil y exige mucho tiempo verificar las razones de las respuestas inesperadas.


Las variables locales se almacenan en una pila, pero las variables de instancia se almacenan en el montón, por lo que hay algunas posibilidades de que se lea un valor anterior en la pila en lugar de un valor predeterminado como sucede en el montón. Por esa razón, el jvm no permite usar una variable local sin inicializarlo.


Las variables locales se declaran principalmente para hacer algunos cálculos. Entonces, es la decisión del programador establecer el valor de la variable y no debe tomar un valor predeterminado. Si el programador, por error, no inicializó una variable local y toma el valor predeterminado, entonces la salida podría ser un valor inesperado. Entonces, en el caso de variables locales, el compilador le pedirá al programador que inicialice con algún valor antes de acceder a la variable para evitar el uso de valores indefinidos.


Podría pensar en seguir 2 razones

  1. Como la mayoría de las respuestas dicen poniendo la restricción de inicializar la variable local, se asegura que a la variable local se le asigna un valor como el programador quiere y asegura que se calculan los resultados esperados.
  2. Las variables de instancia se pueden ocultar al declarar las variables locales (mismo nombre): para garantizar el comportamiento esperado, las variables locales se ven forzadas a que se les inutilice un valor. (Sin embargo, lo evitaría por completo)

Tenga en cuenta que las variables de instancia / miembro final no se inicializan de manera predeterminada. Porque esos son finales y no pueden ser cambiados en el programa después. Esa es la razón por la cual Java no les da ningún valor predeterminado y obliga al programador a inicializarlo.

Por otro lado, las variables de miembros no finales se pueden cambiar más adelante. Por lo tanto, el compilador no los deja sin inicializar, precisamente, porque pueden cambiarse más tarde. En cuanto a las variables locales, el alcance de las variables locales es mucho más limitado. El compilador sabe cuándo se está acostumbrando. Por lo tanto, forzar al programador a inicializar la variable tiene sentido.


El "problema" con el que te vinculas parece describir esta situación:

SomeObject so; try { // Do some work here ... so = new SomeObject(); so.DoUsefulThings(); } finally { so.CleanUp(); // Compiler error here }

La queja del comentarista es que el compilador se muestra reacio a la línea en la sección final, alegando que podría estar sin inicializar. El comentario luego menciona otra forma de escribir el código, probablemente algo como esto:

// Do some work here ... SomeObject so = new SomeObject(); try { so.DoUsefulThings(); } finally { so.CleanUp(); }

El comentarista no está contento con esa solución porque el compilador dice que el código "debe estar dentro de un intento". Supongo que eso significa que parte del código puede generar una excepción que ya no se maneja. No estoy seguro. Ninguna versión de mi código maneja ninguna excepción, por lo que todo lo relacionado con excepciones en la primera versión debería funcionar igual en el segundo.

De todos modos, esta segunda versión del código es la forma correcta de escribirlo. En la primera versión, el mensaje de error del compilador era correcto. La variable so podría estar sin inicializar. En particular, si el constructor SomeObject falla, so no se inicializará, por lo que será un error intentar llamar a so.CleanUp . Siempre ingrese la sección de try luego de que haya adquirido el recurso que finaliza la sección final.

El bloque try - finally después de la inicialización solo está ahí para proteger la instancia de SomeObject , para asegurarse de que se limpia sin importar lo que suceda. Si hay otras cosas que deben ejecutarse, pero no están relacionadas con si la instancia SomeObject fue propiedad asignada, entonces deberían ir en otro bloque try - finally , probablemente uno que envuelva el que he mostrado.

Requerir que las variables se asignen manualmente antes del uso no conduce a problemas reales. Solo genera molestias menores, pero tu código será mejor para eso. Tendrás variables con un alcance más limitado, e try , finally bloques que no intenten proteger demasiado.

Si las variables locales tenían valores predeterminados, entonces en el primer ejemplo habría sido null . Eso realmente no habría resuelto nada. En lugar de obtener un error en tiempo de compilación en el bloque finally , tendría una NullPointerException acechando allí que podría ocultar cualquier otra excepción que pudiera ocurrir en la sección "Hacer algo de trabajo aquí" del código. (¿O las excepciones en las secciones finales se encadenan automáticamente a la excepción anterior? No lo recuerdo. Aun así, tendría una excepción adicional en el camino de la real).