¿Cuál es la diferencia en la memoria entre una variable asignada a nulo y una no asignada?

8

¿Cuál es la diferencia en la memoria entre una variable asignada a nulo y una no asignada?

Sé que hay una diferencia en el uso, pero ¿cuál es la diferencia en la memoria?

abu_abdelbarr
fuente
1
Compartir su investigación ayuda a todos . Cuéntanos qué has probado y por qué no satisfizo tus necesidades. Esto demuestra que te has tomado el tiempo para tratar de ayudarte a ti mismo, nos salva de reiterar respuestas obvias y, sobre todo, te ayuda a obtener una respuesta más específica y relevante. También vea Cómo preguntar
mosquito el

Respuestas:

11

No hay diferencia entre los dos "en memoria".

De la especificación del lenguaje Java, 4.12.5. Valores iniciales de variables :

Cada variable en un programa debe tener un valor antes de usar su valor:

  • Cada variable de clase, variable de instancia o componente de matriz se inicializa con un valor predeterminado cuando se crea (§15.9, §15.10.2):

...

    • Para todos los tipos de referencia (§4.3), el valor predeterminado es nulo.

...

    • Una variable local (§14.4, §14.14) debe recibir explícitamente un valor antes de su uso, ya sea por inicialización (§14.4) o asignación (§15.26), de manera que pueda verificarse utilizando las reglas para la asignación definitiva (§ 16 (Asignación definida)).

A las variables de referencia a nivel de clase u objeto se les asignará un valor nulo.

Las variables de referencia en el nivel del método (pila) tendrán un valor no especificado (utilizando el término C ++). En la práctica, esto a menudo es nulo, pero el estándar no especifica qué hay en la variable de referencia, solo que debe asignarse antes de su uso. El uso de una variable de referencia en la pila de cualquier forma que no sea la asignación como su primer uso dará como resultado un error de compilación.


fuente
Cuando declara una variable sin inicializarla como nula, luego la inicializa dentro de un if-thenbloque, el compilador le dice que la variable puede no inicializarse en el código si el thenbloque no se ejecuta. Si lo inicializa a nulllas compilaciones de código. ¿Por qué es eso dado que "una referencia que no tiene un valor explícitamente asignado tendrá el valor nulo" ?
Tulains Córdova
@Snowman ¿No es eso un detalle de implementación? Solo las variables de clase, las variables de instancia y los componentes de matriz deben inicializarse a sus valores predeterminados. No hay requisitos para las variables locales y no puede usarlas antes de que se inicialicen. Si observara una variable local no inicializada en la memoria, vería lo que la implementación haga con ella, lo que puede no implicar su inicialización nullya que sería un trabajo innecesario hacerlo.
Doval
@Snowman: dado que es ilegal usar un local antes de que se le asigne un valor, si una variable local no inicializada recibe un valor inicial es un detalle de implementación.
David Hammen
1
Por favor vea mi edición más reciente. Culpo al café insuficiente un lunes por la mañana.
4

¿Cuál es la diferencia entre una variable asignada a nulo y otras no asignadas en la memoria?

No existe una variable no asignada en Java. A los miembros de datos de clase que no tienen una asignación explícita se les asigna el valor predeterminado para el tipo, nulo para un objeto o algo similar a 0 para los tipos primitivos.

Las variables locales viven en la pila. (Los locales no primitivos, como MyType footambién viven en la pila, como referencias). La asignación de la pila es simple. Si un bloque contiene declaraciones para variables locales, el espacio que necesitan esas variables locales se reserva en la pila. Si los valores se asignan a esas variables locales al ajustar la pila para acomodar esas variables locales es irrelevante.

La razón por la que no importa es si las variables locales tienen o no un valor asignado en el momento en que la ejecución ingresa al bloque es doble. Una razón es que el tamaño necesario no cambia. Las primitivas tienen un tamaño fijo, y las no primitivas son en realidad referencias. (El objeto referenciado vive en el montón en lugar de en la pila). La segunda razón es que usar una variable local a la que no se le ha asignado un valor es un error de compilación. Esto deja al tiempo de ejecución de Java si se debe dar algún valor (no necesariamente el predeterminado) a una variable local declarada pero no asignada.

David Hammen
fuente
En alguna parte de su respuesta está la explicación: cuando declara una variable sin inicializarla como nula, luego la inicializa dentro de un if-thenbloque, el compilador le dice que la variable puede no inicializarse en el código si el thenbloque no se ejecuta. Si lo inicializa a nulllas compilaciones de código. ¿Por qué es eso dado que "una referencia que no tiene un valor explícitamente asignado tendrá el valor nulo" ? Pero aún no está lo suficientemente claro para mí. ¿Podría explicarlo en otras palabras?
Tulains Córdova
2
Las variables locales no necesitan un valor inicial. Se les debe asignar un valor antes del uso inicial. Si la memoria asociada con esa variable recibe un valor inicial explícito, incluso en el caso de una declaración sin asignación, es un detalle de implementación. La memoria existe (así es como funcionan las pilas), pero ese espacio de memoria se puede dejar lleno con lo que sea que haya en esa memoria antes de ajustar la pila.
David Hammen
@ user61852: que una referencia a la que no se haya asignado explícitamente un valor tendrá un valor nulo para los miembros de la clase, pero no necesariamente para las variables locales. Si está compilando su código con la depuración habilitada, el compilador seguramente inicializará sus variables locales no primitivas no inicializadas en null. Esto simplifica enormemente el desarrollo del depurador de Java. ¿Pero qué pasa si compila con la depuración deshabilitada? Ahora esa inicialización es un trabajo adicional innecesario. Lo que hay en esa memoria es irrelevante porque se sabe que la memoria contendrá un valor válido en el primer uso.
David Hammen
Desde una perspectiva de bytecode, las variables locales se asignan en la pila. Sin embargo, el JITter puede decidir si una entrada de pila en particular no debería almacenarse realmente en la pila, sino que los almacenes y las cargas de esa entrada deberían dirigirse a un registro de CPU en particular. Además, si el JITter determina que una vez que la ejecución alcanza un cierto punto no hay forma de que se lea una entrada de la pila sin haber sido reescrita, puede reasignar el registro asociado de esa entrada para algún otro propósito.
supercat
1

Primero, realmente no hay necesidad de preocuparse por el espacio utilizado por las variables locales. En una línea puedo asignar una matriz de 100,000 enteros que ocuparán más espacio que todas las variables locales que usará.

En segundo lugar, su código es compilado por un compilador que probablemente sea inteligente. Si su variable no se inicializa, no se usa (porque el compilador no permite usar variables no inicializadas). Pero si lo inicializa a cero, ¡todavía no se usa! El compilador descubrirá fácilmente que no se usa y no usará espacio para la variable. Incluso si se usa, el compilador descubrirá fácilmente que el valor es nulo y usará nil en lugar de la variable.

Pero tercero, se trata de micro optimizaciones que no lo ayudarán a optimizar un programa de ninguna manera. Estás intentando guardar cuatro u ocho bytes. Concéntrate en guardar megabytes si quieres guardar algo.

Y por último, aunque algunas personas afirman que las variables siempre deben inicializarse, eso no es cierto en Java. Solo debe establecer una variable en un valor significativo. Supongamos que desea establecer una variable para el nombre de una persona, y se olvida de hacer esto en una ruta de código. Si inicializa ciegamente la variable a cero, el compilador no puede decírselo. Sin la inicialización, el compilador puede y le informará sobre su error.

gnasher729
fuente