Nead aclaración para el siguiente código:
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample.append("B");
System.out.println(sample);
Esto se imprimirá B
para que las pruebas sample
y los referToSample
objetos se refieran a la misma referencia de memoria.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
sample.append("A");
referToSample.append("B");
System.out.println(referToSample);
Esto imprimirá AB
que también prueba lo mismo.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
referToSample.append("A");
System.out.println(sample);
Obviamente, esto arrojará NullPointerException
porque estoy tratando de llamar append
a una referencia nula.
StringBuilder sample = new StringBuilder();
StringBuilder referToSample = sample;
referToSample = null;
sample.append("A");
System.out.println(sample);
Entonces, aquí está mi pregunta, ¿por qué la última muestra de código no arroja? NullPointerException
Porque lo que veo y entiendo de los primeros dos ejemplos es si dos objetos se refieren al mismo objeto, entonces, si cambiamos cualquier valor, también se reflejará en otro porque ambos apuntan a misma referencia de memoria. Entonces, ¿por qué esa regla no se aplica aquí? Si asigno null
a referToSample, la muestra también debería ser nula y debería arrojar una NullPointerException pero no arroja una, ¿por qué?
fuente
sample
está quietosample
. Solo cambiastereferToSample
.sample
yreferToSample
como objetos, pero no son objetos, son variables. Una variable puede contener una referencia a un objeto, pero no es en sí misma un objeto. Es una distinción sutil, pero es básicamente la esencia de tu confusión.volatile
,final
,=
,==
...) cuando se aplica a una variable de objeto afecta al puntero , no el objeto que se refiere.Respuestas:
null
las asignaciones no cambian el valor al destruir globalmente ese objeto. Ese tipo de comportamiento conduciría a errores difíciles de rastrear y comportamientos contrarios a la intuición. Solo rompen esa referencia específica .Para simplificar, digamos que
sample
apunta a la dirección 12345. Probablemente esta no sea la dirección, y solo se usa para simplificar las cosas aquí.La dirección generalmente se representa con el extraño hexadecimal dado1Object#hashCode()
, pero esto depende de la implementación.De las líneas marcadas
See diagram
los diagramas de los objetos en ese momento son los siguientes:Diagrama 1:
Diagrama 2:
El diagrama 2 muestra que la anulación
referToSample
no rompe la referencia desample
al StringBuilder en00012345
.1 consideraciones de GC hacen que esto sea inverosímil.
fuente
hashCode()
no es lo mismo que la dirección de memoriahashCode
normalmente lo definen para devolver un valor que no tiene nada que ver con las direcciones de memoria. Creo que puede exponer su punto sobre referencias a objetos frente a objetos sin mencionarloshashCode
. Los puntos más finos de cómo obtener la dirección de memoria se pueden dejar para otro día.Inicialmente fue como dijiste que
referToSample
se refería a losample
que se muestra a continuación:1. Escenario 1:
2. Escenario 1 (cont.):
Aquí, como
referToSample
se referíasample
, se agregó "B" mientras escribereferToSample.append("B")
Lo mismo sucedió en el escenario 2:
Pero, en 3. Escenario 3: como dijo la hexafracción,
cuando se asigna
null
areferToSample
cuando se referíasample
No cambió el valor en vez de eso me rompe la referencia asample
, y ahora apunta a ninguna parte . Como se muestra abajo:Ahora, como no
referToSample
apunta a ninguna parte , mientras que ustedreferToSample.append("A");
no tendría ningún valor o referencia donde pueda agregar A. Entonces, arrojaríaNullPointerException
.PERO
sample
sigue siendo el mismo que lo había inicializado conStringBuilder sample = new StringBuilder();
por lo que se ha inicializado, por lo que ahora puede agregar A, y no arrojaráNullPointerException
fuente
referToSample = sample;
, se refiere a la muestra, simplemente está copiando la dirección de lo que se hace referenciaEn pocas palabras: asigna nulo a una variable de referencia, no a un objeto.
En un ejemplo cambias el estado de un objeto al que hacen referencia dos variables de referencia. Cuando esto ocurre, ambas variables de referencia reflejarán el cambio.
En otro ejemplo, cambia la referencia asignada a una variable, pero esto no tiene ningún efecto en el objeto en sí, por lo que la segunda variable, que aún se refiere al objeto original, no notará ningún cambio en el estado del objeto.
En cuanto a sus "reglas" específicas:
Nuevamente, se refiere a cambiar el estado de un objeto al que se refieren ambas variables .
Nuevamente, cambia la referencia de una variable que no tiene absolutamente ningún efecto sobre la referencia de la otra variable.
Estas son dos acciones completamente diferentes y darán como resultado dos resultados completamente diferentes.
fuente
Vea este diagrama simple:
Cuando se llama a un método en
referToSample
, a continuación,[your object]
se actualiza, por lo que afectasample
también. Pero cuando dicesreferToSample = null
, simplemente estás cambiando a qué sereferToSample
refiere .fuente
Aquí 'muestra' y 'referToSample' hacen referencia al mismo objeto. Ese es el concepto de puntero diferente que accede a la misma ubicación de memoria. Entonces, asignar una variable de referencia a nulo no destruye el objeto.
significa que 'referToSample' solo apunta a nulo, el objeto sigue siendo el mismo y otras variables de referencia funcionan bien. Entonces, para 'muestra' que no apunta a nulo y tiene un objeto válido
funciona bien. Pero si intentamos agregar un valor nulo a 'referToSample', mostrará NullPointException. Es decir,
Es por eso que obtuvo NullPointerException en su tercer fragmento de código.
fuente
Siempre que se usa una nueva palabra clave, se crea un objeto en el montón
1) Ejemplo de StringBuilder = new StringBuilder ();
2) StringBuilder referToSample = muestra;
En 2) la referencia de referSample se crea en la misma muestra de objeto
por lo tanto, referToSample = null; está anulando solo la referencia referSample que no da ningún efecto a la muestra, por eso no obtiene la excepción de puntero NULL gracias a la recolección de basura de Java
fuente
Simplemente fácil, Java no tiene paso por referencia, solo pasa la referencia del objeto.
fuente