¿Por qué Java no tiene un constructor de copia?

¿Por qué Java no es compatible con un constructor de copia como en C ++?

Java lo hace Simplemente no se llaman implícitamente como si estuvieran en C ++ y sospecho que esa es su verdadera pregunta.

En primer lugar, un constructor de copia no es más que:

public class Blah { private int foo; public Blah() { } // public no-args constructor public Blah(Blah b) { foo = b.foo; } // copy constructor } 

Ahora C ++ llamará implícitamente al constructor de copia con una statement como esta:

 Blah b2 = b1; 

La clonación / copia en esa instancia simplemente no tiene sentido en Java porque todos los b1 y b2 son referencias y no objetos de valor como lo son en C ++. En C ++ esa statement hace una copia del estado del objeto. En Java, simplemente copia la referencia . El estado del objeto no se copia, por lo que invocar implícitamente el constructor de copia no tiene sentido.

Y eso es todo lo que hay realmente.

De Bruce Eckel :

¿Por qué [un constructor de copias] funciona en C ++ y no en Java?

El constructor de copia es una parte fundamental de C ++, ya que automáticamente hace una copia local de un objeto. Sin embargo, el ejemplo anterior demuestra que no funciona para Java. ¿Por qué? En Java, todo lo que manipulamos es un identificador, mientras que en C ++ puedes tener entidades similares a las de un manipulador y también puedes pasar los objetos directamente. Para eso está el constructor de copias C ++: cuando quieres tomar un objeto y pasarlo por valor, duplicando así el objeto. Por lo tanto, funciona bien en C ++, pero debe tener en cuenta que este esquema falla en Java, así que no lo use.

(Recomiendo leer la página completa, en realidad, comience aquí en su lugar).

Creo que la respuesta a esto es muy interesante.

Por un lado, creo que en Java todos los objetos están en el montón, y si bien no tienes punteros, tienes “referencias”. Las referencias tienen una copia simétrica y java realiza un seguimiento interno de los recuentos de referencia para que su recolector de basura sepa de qué se puede deshacer.

Como solo accede a objetos a través de referencias copiables, la cantidad real de veces que necesita copiar un objeto se reduce enormemente (por ejemplo, en C ++ solo pasar un objeto a una función (por valor) da como resultado la construcción de objetos nuevos, en Java solo se pasa la referencia al objeto). Los diseñadores probablemente pensaron que el clon () sería suficiente para los usos restantes.

Esta es solo mi opinión (estoy seguro de que hay una respuesta justificable)

Los constructores de copia en C ++ son principalmente útiles cuando envía o devuelve instancias de clases por valor, ya que es cuando el constructor de copia se activa de forma transparente.

Como en Java todo se devuelve por referencia, y la VM está orientada hacia la asignación dinámica, realmente no había una justificación para las complejidades de un constructor de copia.

Además, dado que todo es por referencia, un desarrollador a menudo tendría que proporcionar su propia implementación y decisión sobre cómo clonar los campos.

¿Adivina que pensaron que solo puedes hacer un método clone ()?

Es algo que hace. Cuando las copias superficiales son correctas, tiene [clone ()] ( http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#clone ()) y cuando aren ‘ Tienes que implementar una copia profunda como C ++.

La única diferencia sustancial es que es un método de fábrica en lugar de un constructor propiamente dicho, pero en términos de flexibilidad y capacidad de prueba es probable que sea algo bueno.

No soy muy progtwigdor en C ++, pero sí recuerdo una regla sobre los “tres amigos”: copiador, operador de asignación y destructor. Si tiene uno, entonces probablemente necesite los tres.

Entonces, ¿tal vez sin un destructor en el lenguaje, no querían incluir un constructor de copia? Solo una suposición.

Bueno, puede. Simplemente no se crea implícitamente. Si tuviera que adivinar, probablemente esté relacionado con el hecho de que los objetos Java siempre se asignan en forma de stack.

En C ++, el constructor de copia predeterminado es una copia superficial para miembros. Si una clase posee memoria asignada en el montón (a través de un puntero sin formato), esto hará que la copia comparta elementos internos con el original, que no es lo que desea.

Imagine por un momento que Java tenía este comportamiento. Cualquier clase que tenga campos que sean objetos (léase: esencialmente todos ellos) tendría un comportamiento incorrecto, y usted tendría que anularla usted mismo. En el 99% de los casos, no ha guardado ningún problema. Además, acaba de crear una trampa sutil para usted mismo: imagine que accidentalmente se olvida de anular el constructor de copia predeterminado. Si se generó de forma predeterminada, e intenta usarlo, el comstackdor no se quejará en absoluto, pero su progtwig se comportará mal en tiempo de ejecución.

Incluso si hicieron un constructor de copia predeterminado que realiza una copia profunda, no estoy seguro de que sea particularmente útil. No solo tiende a realizar menos copias en Java que en C ++ de todos modos, pero no siempre quiere copiar en profundidad un campo.

Los objetos que acaba de adquirir, y los objetos a los que tiene referencias porque los necesita, pero no es responsable de ellos, son los mismos, solo campos. La propiedad y los préstamos no son conceptos de primera clase. Para los objetos que posee, querrá copiarlos en profundidad (a menos que sean inmutables, en cuyo caso no debería molestarse), y para los objetos a los que hace referencia, quiere copiar la referencia.

Yo diría que un constructor de copias que simplemente copia profundamente todo lo que no sería adecuado para muchas clases tampoco. Ciertamente, más que una copia superficial por defecto, sin embargo.

Java tiene copiar Constructor
Nota: En lugar de demo d2 = nueva demostración (d1) , puede escribir la demostración d2 = d1
Diferencia principal b / n dos
demo d2 = nueva demostración (d1) significa que se crea un nuevo objeto y se le asigna memoria.
La demostración d2 = d1 implica que solo se crea una variable de referencia que usa la misma dirección de memoria del objeto d1 y, por lo tanto, d2 no asigna la memoria separada.

Sintaxis del constructor de copia:
Ver abajo El primer constructor de Copias es muy fácil :))
classname (int datafield) // Simple Constructor
{
this.datafield = campo de datos;
}

nombre de clase (objeto de nombre de clase)
{
datafield = object.datafield; // Vea el ejemplo siguiente
}
Ahora para llamar
{

classname obj = new classname ();

classname anotherObject = obj; // o classname anotherObject = new classname (obj)

}


  demostración de clase
 {
     longitud int privada;

     amplitud privada;

     radio interno privado;

     demo (int x, int y)

     {
         longitud = x;
         amplitud = y;
     }
     área int ()
     {
         longitud de retorno * ancho;
     }

     // Copy Constructor
     demo (demo obj)
     {
         longitud = obj.length;
         amplitud = obj.breadth;
     }


     public static void main (String args [])
     {
         demo d1 = nueva demostración (5,6);
         demo d2 = nueva demostración (d1); // Invoca Copiar constructura
         System.out.println ("Área para d1 object =" + d1.area ());
         System.out.println ("Área para d2 object =" + d2.area ());

     }
 }