validar solucion sirve que para error java memory-management null deep-copy shallow-copy

solucion - despejar o establecer null para objetos en java



null java para que sirve (7)

Hace poco estuve buscando liberar la memoria ocupada por objetos Java. Al hacer eso, me confundí sobre cómo se copian los objetos (superficiales / profundos) en Java y cómo evitar accidentalmente borrar / anular objetos mientras todavía están en uso.

Considera seguir escenarios:

  1. pasar un ArrayList<Object> como argumento a un método.
  2. pasar un ArrayList<Object> a una clase ejecutable para ser procesada por un hilo.
  3. poniendo un ArrayList<Object> en un HashMap .

Ahora en estos casos, si llamo list = null; o list.clear(); , ¿qué pasa con los objetos? En cuyo caso los objetos se pierden y en cuyo caso solo la referencia se establece en nulo?

Supongo que tiene que ver con la copia superficial y profunda de objetos, pero ¿en qué casos ocurre una copia superficial y en qué caso ocurre una copia profunda en Java?


Hace poco estuve buscando liberar la memoria ocupada por objetos java.

Un pequeño consejo.

Por lo general, es una mala idea pensar en esto. Y generalmente es una peor idea tratar de "ayudar". En el 99.8% de los casos, el recolector de basura de Java puede hacer un mejor trabajo al recolectar la basura si realmente solo lo deja funcionar ... y no desperdicie su esfuerzo asignando cosas null . De hecho, lo más probable es que los campos que está anulando estén en objetos que están a punto de volverse inalcanzables de todos modos. Y en ese caso, el GC ni siquiera va a mirar los campos que has anulado.

Si tomas esta visión (pragmática), todo lo que piensas sobre copias superficiales versus copias profundas y cuándo es seguro anular las cosas es discutible.

Hay un pequeño porcentaje de casos en los que es aconsejable asignar null ... para evitar fugas de almacenamiento a mediano o largo plazo. Y si se encuentra en una de esas situaciones excepcionales en las que "reciclar" objetos es en realidad una buena idea, entonces anular también es aconsejable.


Depende de cuántas variables se referencian a cada uno de tus objetos, para explicar esto sería mejor algún código:

Object myAwesomeObject = new Object(); List<Object> myList = new ArrayList<Object>(); myList.add(myAwesomeObject); myList = null; // Your object hasn''t been claimed by the GC just yet, your variable "myAwesomeObject" is still refering to it myAwesomeObject = null; // done, now your object is eligible for garbage collection.

Por lo tanto, no depende de si transfiere ArrayList como argumento a un método o similar, depende de cuántas variables sigan refiriéndose a sus objetos.


En primer lugar, nunca establece un objeto como nulo. Ese concepto no tiene significado. Puede asignar un valor de null a una variable , pero necesita distinguir muy cuidadosamente entre los conceptos de "variable" y "objeto". Una vez que lo haga, su pregunta se responderá por sí misma :)

Ahora, en términos de "copia superficial" versus "copia profunda", probablemente valga la pena evitar el término "copia superficial" aquí, ya que generalmente una copia superficial implica la creación de un nuevo objeto, pero simplemente copia directamente los campos de un objeto existente. Una copia profunda también tomaría una copia de los objetos referidos por esos campos (para campos de tipo de referencia). Una tarea simple como esta:

ArrayList<String> list1 = new ArrayList<String>(); ArrayList<String> list2 = list1;

... no hace ni una copia superficial ni una copia profunda en ese sentido. Simplemente copia la referencia. Después del código anterior, list1 y list2 son variables independientes, simplemente tienen los mismos valores (referencias) en el momento. Podríamos cambiar el valor de uno de ellos, y no afectaría al otro:

list1 = null; System.out.println(list2.size()); // Just prints 0

Ahora, si en lugar de cambiar las variables , realizamos un cambio en el objeto al que se refieren los valores de las variables, ese cambio también será visible a través de la otra variable:

list2.add("Foo"); System.out.println(list1.get(0)); // Prints Foo

Volviendo a su pregunta original, nunca almacena objetos reales en un mapa, lista, matriz, etc. Solo almacena referencias . Un objeto solo puede ser recolectado como basura cuando no hay formas de que el código "en vivo" llegue a ese objeto. Entonces en este caso:

List<String> list = new ArrayList<String>(); Map<String, List<String>> map = new HashMap<String, List<String>>(); map.put("Foo", list); list = null;

... el objeto ArrayList aún no puede ser recolectado como basura, porque el Map tiene una entrada que hace referencia a él.


Java GC reclama automáticamente los objetos cuando no están referenciados en ningún lugar. Entonces, en la mayoría de los casos, tendrá que establecer la referencia como null explícitamente

Tan pronto como el alcance de la variable finalice, el objeto será elegible para GC y se liberará si ninguna otra referencia apunta al objeto.

Java pasa por valor, por lo que si establece la lista como null en el método, no afectará la referencia original que se le pasó en el método.

public class A{ private List<Integer> list = new ArrayList<Integer>(); public static void main(String[] args) { A a = new A(); B b = new B(); b.method(a.list); System.out.println(a.list.size()); //Will print 0 and not throw NullPointerException } } class B{ public void method(List<Integer> list){ list = null; //just this reference is set to null and not the original one //so list of A will not be GCed } }


Si coloca la lista en un mapa hash, el mapa hash ahora contiene una referencia a la lista.

Si pasa la lista como un argumento a un método, el método tendrá una referencia durante la duración del método.

Si pasa a un hilo para ser manipulado, el hilo tendrá una referencia al objeto hasta que termine.

En todos estos casos, si establece list = null , las referencias se mantendrán, pero desaparecerán cuando desaparezcan estas referencias.

Si simplemente borra la lista, las referencias seguirán siendo válidas, pero ahora apuntarán a una lista que se haya vaciado repentinamente, por medios que pueden ser desconocidos para el programador y pueden considerarse un error, especialmente si usa el hilo.


Si pasó una lista de arreglos a un método, list = null no tendrá efecto si hay una referencia en vivo a la lista en algún lugar, por ejemplo, en el código de llamada. Si llama a list.clear () en cualquier parte del código, las referencias a los objetos de esta lista se anularán. Pasar una referencia a un método no es una copia superficial, es pasar el valor por referencia de referencia


Para borrar la variable

De acuerdo a mi conocimiento,

Si vas a reutilizar la variable, utiliza

Object.clear();

Si no va a reutilizar, defina

Object=null;

Nota: Compare con removeAll (), clear () es más rápido.

Por favor, corríjame si estoy equivocado....