Pregunta

¿Por qué Java no admite un constructor de copia como en C ++?

¿Fue útil?

Solución

Java lo hace. Simplemente no se llaman implícitamente como en C ++ y sospecho que esa es tu 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 declaración como esta:

Blah b2 = b1;

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

Y eso es todo lo que hay realmente.

Otros consejos

De Bruce Eckel :

  

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

     

El constructor de copia es un elemento fundamental.   parte de C ++, ya que automáticamente   Hace una copia local de un objeto. Todavía   el ejemplo anterior demuestra que lo hace   No funciona para Java. ¿Por qué? En java   Todo lo que manipulamos es un   manejar, mientras que en C ++ puedes tener   entidades similares a asas y también puede   Pasa alrededor de los objetos directamente.   Eso es lo que el constructor de copia C ++   es para: cuando quieres tomar un   objeto y pasarlo en valor, por lo tanto   duplicando el objeto. Asi funciona   bien en C ++, pero debes mantenerte   importa que este esquema falle en Java,   así que no lo uses.

(Recomiendo leer la página completa: en realidad, inicie 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 mientras no tienes punteros, tienes " Referencias " ;. Las referencias tienen copia de symantics y java realiza un seguimiento interno de los recuentos de referencias para que su recolector de basura sepa de qué es seguro deshacerse.

Dado que solo accede a los objetos a través de referencias copiables, el número real de veces que necesita copiar un objeto se reduce considerablemente (por ejemplo, en C ++, el simple hecho de pasar un objeto a una función (por valor) hace que se construyan nuevos objetos). , en Java solo se pasa la referencia al objeto). Los diseñadores probablemente pensaron que clone () sería suficiente para los usos restantes.

& nbsp;

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

Los constructores de copia en C ++ son principalmente útiles cuando está enviando o devolviendo instancias de clases por valor, ya que es cuando el constructor de copia se activa de forma transparente.

Dado que en Java todo se devuelve por referencia, y la VM está orientada hacia la asignación dinámica, realmente no hubo 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 campos.

Supongo que pensaron que puedes hacer un método clone () en su lugar?

En cierto modo lo hace. Cuando las copias superficiales están bien, tiene [clone ()] ( http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#clone ()) y cuando no lo están tienes que implementar una copia profunda al igual que C ++.

La única diferencia importante es que es un método de fábrica en lugar de un constructor propio, pero en términos de flexibilidad y comprobabilidad, eso es probablemente algo bueno.

No soy un programador de C ++, pero parece que recuerdo una regla sobre los " tres amigos " - Copia constructor, operador de asignación, y destructor. Si tienes uno, es probable que necesites los tres.

¿Entonces tal vez sin un destructor en el lenguaje, no quisieran incluir un constructor de copia? Sólo una conjetura.

Bueno, puede. Simplemente no se crea implícitamente. Si tuviera que adivinar, probablemente esté relacionado con el hecho de que los objetos Java siempre están asignados en montón.

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

Imagina por un momento que Java tuvo este comportamiento. Cualquier clase que tenga campos que sean objetos (leídos: esencialmente todos) tendrá un comportamiento incorrecto, y usted debería anularlo usted mismo. Para el 99% de los casos, no le has ahorrado ningún problema a nadie. Además, acabas de crear una trampa sutil para ti mismo: imagina que olvidaste accidentalmente anular el constructor de copia predeterminado. Si se generó de forma predeterminada e intenta usarlo, el compilador no se quejará en absoluto, pero su programa se comportará mal en el tiempo de ejecución.

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

Los objetos que acaba de poseer y los objetos a los que tiene referencias porque los necesita, pero de los que no es responsable, son los mismos, solo campos. La propiedad y los préstamos no son conceptos de primera clase. Para los objetos que posees, querrás copiarlos en profundidad (a menos que sean inmutables, en cuyo caso no deberías molestarte), y para los objetos a los que solo tienes una referencia, quieres copiar la referencia.

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

Java have copy Constructor
Nota: en lugar de demo d2 = nueva demo (d1) , puede escribir demo d2 = d1
Principal diferencia b / w dos
demo d2 = nueva demo (d1) significa que se crea un nuevo objeto y memoria asignada Pero la demo d2 = d1 implica que solo se crea una variable de referencia que utiliza la misma dirección de memoria del objeto d1 y, por lo tanto, d2 no asignado memoria separada

Sintaxis del constructor de copia:
Vea a continuación Ejemplo del primer constructor Copiar es muy fácil :))
nombre de clase (campo de datos int) // Constructor simple
{
this.datafield = campo de datos;
}

classname (classname object)
{
 campo de datos = object.datafield; // Vea el siguiente ejemplo
}
Ahora para llamar
{

classname obj = new classname ();

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

}

 class demo
{
    private int length;

    private int breadth;

    private int radius;

    demo(int x,int y)

    {
        length=x;
        breadth=y;
    }
    int area()
    {
        return length*breadth;
    }

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


    public static void main(String args[])
    {
        demo d1=new demo(5,6);
        demo d2=new demo(d1);//Invokes Copy Constructure
        System.out.println("Area for d1 object="+d1.area());
        System.out.println("Area for d2 object="+d2.area());

    }
}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top