Pergunta

Por que não suporte a Java um construtor de cópia, como no C++?

Foi útil?

Solução

Java faz. Eles simplesmente não são chamados implicitamente como eles estão em C ++ e eu suspeito que é a sua pergunta real.

Em primeiro lugar, um construtor de cópia é nada mais do que:

public class Blah {
  private int foo;

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

Agora, C ++ irá chamar implicitamente o construtor de cópia com uma declaração como esta:

Blah b2 = b1;

A clonagem / cópia nesse caso simplesmente não faz sentido em Java porque todos b1 e b2 são referências e não o valor objetos como eles estão em C ++. Em C ++ essa afirmação faz uma cópia do estado do objeto. Em Java ele simplesmente copia o referência . o estado do objeto não é copiado de modo implicitamente chamando o construtor de cópia não faz sentido.

E isso é tudo o que há para realmente.

Outras dicas

A partir Bruce Eckel :

Por que [um construtor de cópia] trabalho em C ++ e não Java?

O construtor de cópia é um direito fundamental parte de C ++, uma vez que automaticamente faz uma cópia local de um objeto. Ainda o exemplo acima mostra que ele faz não funcionar para Java. Por quê? em Java tudo o que nós manipulamos é um alça, enquanto que em C ++ você pode ter lidar com-like entidades e você também pode passar ao redor dos objetos diretamente. Isso é o que o C ++ construtor de cópia é a seguinte: quando você quer tomar uma objeto e passá-la em termos de valor, assim duplicar o objeto. Então ele funciona bem em C ++, mas você deve ter em mente que este esquema de falha em Java, por isso não usá-lo.

(Eu recomendo a leitura da página inteira - na verdade, começar aqui vez .)

Eu acho que a resposta para isso é muito interessante.

Por um lado, eu acredito que em Java todos os objetos são na pilha e, enquanto você não tem ponteiros, você tem "Referências". Referências tenham copiar symantics e java mantém internamente o controle de contagens de referência de modo que seu coletor de lixo sabe o que está segura de se livrar de.

Uma vez que só acessar objetos através de referências copiáveis, o número real de vezes que você precisa copiar um objeto é muito reduzida (por exemplo, em C ++ apenas passando um objeto para uma função (por valor) resulta em novos objetos sendo cópia construído , em Java apenas a referência para o objecto é passado). Os designers provavelmente imaginou que clone () seria suficiente para as demais utilizações.

Esta é apenas a minha opinião (eu tenho certeza que há uma resposta justificável)

construtores de cópia em C ++ são principalmente úteis quando você está enviando ou retornar instâncias de classes por valor, desde que é quando o construtor de cópia é transparente ativada.

Uma vez que em Java tudo é retornado por referência, eo VM é voltada para a alocação dinâmica, realmente não havia justificativa para as complexidades de um construtor de cópia.

Além disso, uma vez que tudo é por referência, um desenvolvedor, muitas vezes têm de fornecer sua própria implementação e decisão sobre como clonar campos.

acho que eles pensaram que você pode apenas fazer um método clone () em vez disso?

É o tipo de faz. Quando as cópias rasas estão bem você tem [clone ()] ( http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#clone ()) e quando eles não são você tem que implementar uma cópia profunda como C ++.

A única diferença substancial é que é um método de fábrica em vez de um construtor adequada, mas em termos de flexibilidade e capacidade de teste que é provavelmente uma boa coisa.

Eu não sou muito de um programador C ++, mas eu me lembro de uma regra sobre os "três amigos" - construtor de cópia, operador de atribuição e destruidor. Se você tem um, então você provavelmente precisará de todos os três.

Então, talvez sem um destructor na língua, eles não querem incluir um construtor de cópia? Apenas um palpite.

Bem, ele pode. Ele só não são criados implicitamente. Se eu tivesse que adivinhar, está provavelmente relacionado ao fato de que objetos Java são sempre heap-alocado.

Em C ++, o construtor de cópia padrão é uma cópia superficial membro-wise. Se uma classe possui memória alocada no heap (através de um ponteiro não processado), isso fará com que a cópia para internos compartilhar com o original, o que não é o que você quer.

Imagine por um momento que o Java teve esse comportamento. Qualquer classe que tem campos que são objetos (leia-se: essencialmente, todos eles) teriam o comportamento errado, e que você precisa para substituí-lo sozinho. Para 99% dos casos, você não salvou ninguém nenhum problema. Além disso, você acabou de criar uma armadilha sutil para si mesmo - imagine que você acidentalmente esquecer de substituir o construtor de cópia padrão. Se ele foi gerado por padrão, e você tentar usá-lo, o compilador não vai reclamar em tudo, mas o seu programa irá se comportar mal durante a execução.

Mesmo que eles fizeram um construtor de cópia padrão que executa uma cópia profunda, eu não estou certo de que seria particularmente útil. Não só você tendem a realizar menos cópias em Java do que o C ++ de qualquer maneira, mas nem sempre você deseja copiar profunda um campo.

Objetos que você simplesmente próprio, e objetos que você mantém referências a porque você precisa deles, mas não são responsáveis ??por, são os mesmos - apenas campos. Propriedade e empréstimos não são conceitos de primeira classe. Para objetos que você possui, que você gostaria de copiá-los profunda (a menos que eles são imutáveis, caso em que você não deve se preocupar), e para objetos que você só segurar uma referência para, você deseja copiar a referência.

Eu diria que um construtor de cópia que apenas mindlessly profundas-copia tudo não seria adequado para muitas classes, qualquer um. Certamente mais do que por padrão, embora de cópia superficial.

Java tem Construtor de cópia
Nota:em Vez de demo d2=new demo(d1) ,você pode escrever demo d2=d1
Principal diferença b/w dois
demo d2=new demo(d1) significa um novo objeto é criado e é alocada de memória, Mas
demo d2=d1 implica apenas a variável de referência é criada que usa o mesmo endereço de memória do objeto d1 e, portanto, d2 não atribuído separados de memória.

A sintaxe do construtor de cópia:
Veja abaixo Exemplo, o primeiro construtor de Cópia é muito fácil :))
classname(int datafield) //Construtor Simples
{
isso.datafield=datafield;
}

classname(o nome da classe de objeto)
{
datafield=objeto.datafield;//Veja abaixo um exemplo de
}
Agora para Chamar
{

o nome da classe obj=new nomedaclasse();

classname anotherObject=obj;//ou classname anotherObject=new nomedaclasse(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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top