En Java, ¿qué es una copia superficial?

java.util.Calendar.clone () devuelve “… un nuevo calendario con las mismas propiedades” y devuelve “una copia superficial de este calendario”.

Esto no parece ser una copia superficial como se responde aquí en SO. Esa pregunta está etiquetada como independiente del lenguaje, Java no parece seguir la definición de agnóstico del lenguaje. A medida que paso por el código, noto que la estructura y los elementos se copian en este nuevo objeto, más que en la estructura independiente del lenguaje.

En Java, ¿qué es una copia superficial?

¿Cómo difiere de una copia profunda de Java (si es que existe)?

Una copia superficial simplemente copia los valores de las referencias en la clase. Una copia profunda copia los valores. dado:

class Foo { private Bar myBar; ... public Foo shallowCopy() { Foo newFoo = new Foo(); newFoo.myBar = myBar; return newFoo; } public Foo deepCopy() { Foo newFoo = new Foo(); newFoo.myBar = myBar.clone(); //or new Bar(myBar) or myBar.deepCopy or ... return newFoo; } } Foo myFoo = new Foo(); Foo sFoo = myFoo.shallowCopy(); Foo dFoo = myFoo.deepCopy(); myFoo.myBar == sFoo.myBar => true myFoo.myBar.equals(sFoo.myBar) => true myFoo.myBar == dFoo.myBar => **false** myFoo.myBar.equals(dFoo.myBar) => true 

En este caso, la copia superficial tiene la misma referencia ( == ) y la copia profunda solo tiene una referencia equivalente ( .equals() ).

Si se realiza un cambio en el valor de una referencia copiada superficialmente, la copia refleja ese cambio porque comparte la misma referencia. Si se realiza un cambio en el valor de una referencia profundamente copiada, entonces la copia no refleja ese cambio porque no comparte la misma referencia.

C-ismo

 int a = 10; //init int& b = a; //shallow - copies REFERENCE int c = a; //deep - copies VALUE ++a; 

Resultado:

 a is 11 *b is 11 c is 10 

La copia superficial es solo un conjunto de punteros a las mismas ubicaciones de memoria. En realidad, no crea una copia real, por lo que el uso de la memoria es menor.

En el caso de una copia profunda, se crea una copia exacta del segmento de memoria y los punteros se configuran en nuevas ubicaciones de memoria. Entonces, teoréticamente, el consumo de memoria debería ser dos veces en este caso.

Una copia superficial es una copia del puntero de referencia al objeto, mientras que una copia profunda es una copia del objeto en sí. En Java, los objetos se mantienen en segundo plano, con lo que normalmente interactúas cuando se trata de los objetos son los punteros. Los nombres de las variables apuntan al espacio de la memoria del objeto. Se realiza una copia poco profunda cuando configura una variable igual a otra, por ejemplo:

 Object B = A; 

Se podría hacer una copia profunda obteniendo las propiedades del objeto A y poniéndolas en un nuevo objeto B.

 Object B = new Object(A.getProperty1(), A.getProperty2()...); 

Esto afecta el comportamiento del progtwig en el sentido de que si realiza una copia superficial y realiza una tarea en ella, eso afecta a todas las copias superficiales del objeto. Si realiza un cambio en una copia profunda, solo esa copia se verá afectada. Espero que esto sea lo suficientemente detallado para ti.

El documento de 1.6 documentos Calendar.clone como “Crea y devuelve una copia de este objeto”. Una copia poco profunda literal especificada por Object.clone no tendría ningún sentido. Java usa el término “copia superficial” en un sentido bastante típico.

Parece ser un error en la documentación. No veo cómo el método Calendar.clone de Android cumple con la definición típica (en Java o no) de una “copia superficial”.

¿De dónde sacas esta documentación?

Los documentos oficiales de Java 6 en java.sun.com simplemente hacen que Calendar.clone () devuelva una copia del objeto. Sin mención de superficial.

De manera más general, una copia superficial en Java es aquella en la que se obtiene una nueva referencia de objeto pero el nuevo objeto contiene (directa o indirectamente) referencias a datos en el original.

Por ejemplo:

 class MyClass{ private List innerList; public MyClass(List list) { innerList = list; } //Some code... public Object clone(){ return new MyClass(innerList); } } 

devuelve una copia superficial en su clon ().

En primer lugar, el Javadoc de ArrayList es algo erróneo si hablamos de matrices unidimensionales, ya que utiliza el método copyOf en Arrays. ¡Así que clone () devuelve una copia unidimensional, al menos desde 1.5 (no realicé más pruebas)! Entonces eso es lo que significa “superficial” en Java: unidimensional

Puede leer más aquí: http://www.javapractices.com/topic/TopicAction.do?Id=3 . ¡Así que clonar () no es una copia superficial! Si desea una copia superficial real de una matriz unidimensional, simplemente haga referencia a ella:

 Array a = new Array(); Array b = a; //a is only a shallow copy, nice for synchronisation 

Las matrices en Java son engañosas, también porque Java pasa de a-valor, ¡pero los valores de las matrices son solo sus punteros! Por otro lado, esto nos permite sincronizar los objetos, que es una gran cosa. Aún así, hay algunos problemas si usa matrices dentro de matrices (o ArrayLists), porque un clon () de la matriz de contenedores (o ArrayList) no copiará sus valores, ¡solo sus referencias! ¡Así que simplemente no debería poner ningún conjunto en una matriz, solo debería tratar con objetos en una matriz!

Y Javadoc es difícil de entender a veces, así que prueba un poco …

¡Que te diviertas!

Una copia superficial solo copia la referencia del objeto en la referencia del objective. No crea un nuevo objeto en el montón. Por defecto, Java realiza una clonación superficial utilizando la función clone ().

Para obtener un nuevo objeto en el montón, uno tiene que realizar una clonación profunda que puede implementarse mediante Serialización y Deserialización.

En una copia superficial, el objeto clon tiene una copia de valores primitivos pero las referencias a objetos se refieren a los mismos objetos que la copia original. Las copias superficiales tienen un inconveniente importante, el objeto clonado y la copia original se refieren al mismo objeto de dirección. Cualquier cambio que haga el objeto clonado en el objeto de dirección también se reflejará en la copia original, que es un comportamiento no deseado. Lo que realmente queríamos es dos copias separadas del objeto de usuario. Copia profunda viene a nuestro rescate para este tipo de situación.

Copia profunda clona no solo los valores primitivos, también crea copias de referencias de objetos.

Puede echar un vistazo al ejemplo de trabajo aquí: https://codingninjaonline.com/2017/11/09/deep-vs-shallow-copy/