web-dev-qa-db-ja.com

コピーコンストラクタが必要な理由と、java

コピーコンストラクターを使用していましたが、スタックオーバーフローなどのリンクも使用しました。しかし、私は次の点について明確ではありません。

  1. コピーコンストラクターが必要な理由
  2. コピーコンストラクタが必要な場合

Copy Constructorを使用するのに必要な正確な状況またはシナリオは何ですか。誰かが例を使って説明したり、リンクを指摘して、明確に理解して理解できるようにすることができます。

以下は、コピーコンストラクターとは何かを理解するために行ったリンクです。

http://www.programmerinterview.com/index.php/Java-questions/how-copy-constructors-work/

https://deepeshdarshan.wordpress.com/2013/12/05/copy-constructors-in-Java/

2番目のリンクは、コピーコンストラクターを使用する「理由」と「場所」を説明しています。しかし、それでもまだ明確ではありません。

以下は私のクラスEmployee.Javaです

package com.test;

/**
 * @author avinashd
 *
 */
public class Employee {

    private String rollNo;
    private String name;

    //constructor
    public Employee(String rollNo, String name){

        this.rollNo = rollNo;
        this.name = name;
    }

    //copy constructor
    public Employee(Employee employee){

    this.rollNo = employee.rollNo;
    this.name = employee.name;

    }

    public String getRollNo() {
        return rollNo;
    }

    public void setRollNo(String rollNo) {
        this.rollNo = rollNo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Copy Constructorは、既存のオブジェクトと同じ値を持つオブジェクトの正確なコピーを作成するために使用されます。

たとえば、値がrollNo: 1およびname: avinashのEmployeeがあるとします。コピーコンストラクターは、rollNo: 1およびname: avinashの値を持つ同様のオブジェクトを作成します。ただし、どちらも2つの異なるオブジェクトであり、onオブジェクトの値を変更しても、別のオブジェクトには影響しません。

ここの質問は

次のようなコンストラクタがある場合

public Employee(String rollNo, String name){
    this.rollNo = rollNo;
    this.name = name;
}

オブジェクトを作成します。同じコンストラクターを呼び出して、別のオブジェクトを作成できます。しかし、なぜコピーコンストラクターを呼び出す必要がありますか?説明してください

33
Avinash Reddy

すべてのパラメーターを渡すコンストラクターの代わりにコピーコンストラクターを使用する2つの理由があります。

  1. 多くの属性を持つ複雑なオブジェクトがある場合、コピーコンストラクタを使用する方がはるかに簡単です
  2. クラスに属性を追加する場合、他のコンストラクタのすべての出現を変更するのではなく、この新しい属性を考慮するようにコピーコンストラクタを変更するだけです。
34
Serge Ballesta

コピーコンストラクターは、慣例により、オブジェクトのディープコピーを提供する必要があります。他の回答ですでに述べたように、コピーコンストラクターが提供する主な利便性は、オブジェクトが複雑になりすぎることです。 Java.lang.Cloneableは(ほぼ)同様の宣言を提供することに注意してください。

ただし、Cloneableインターフェイスよりもコピーコンストラクタを使用することには多くの利点があります。

  1. インターフェースとしてのCloneableは、実際にはメソッドを提供しません。有効にするためには、Java.lang.Objectcloneメソッドをオーバーライドする必要があります。これは、インターフェイスの直感に反する使用法です。

  2. cloneObjectを返します。使用するためには、型キャストする必要があります。これは厄介で、実行時エラーにつながる可能性があります。

  3. cloneメソッドの文書化は不十分です。 cloneの場合、変更可能なオブジェクトを指す最終フィールドがあると物事が台無しになる可能性があります。

  4. 最も重要なのは、コピーコンストラクターがサブクラスのインスタンスを取り込み、ディープコピーできることです。 IMO、これはコピーコンストラクタが本当に輝くところです。

より多くの利点があります(Joshua BlochのEffective Java 2eを参照)が、これらは私がこれまで取り組んできたことに最も関連している点です。

[1] Java言語には何も実際にディープコピーのデフォルト構造を提供しません。オブジェクトは、Cloneableを実装することで、ディープコピーできることをプログラマに伝えることができます。またはコピーコンストラクターを提供します。

34
skytreader

既に持っているものとまったく同じ値を持つ別のEmployeeインスタンスが必要な場合はどうなりますか?.

電話しますか?

setName(oldEmployee.getName())..
setRollNumber(oldEmployee.getRollNumber())..
etc..

それをする代わりに、これを使用してください

Employee copyOfEmployeeOne=new Employee(employeeOneInstance);
// no need of a sequence of setters..
5
TheLostMind

別のケースは、オブジェクトの「履歴」値を保存することです。

したがって、単一のオブジェクトがありますが、その状態を変更するたびに、ArrayListまたは任意のデータ構造に追加する必要があります。

2
zubergu

コピーコンストラクターは、Object.clone()メソッドよりも多くの利点があります。

  1. インターフェースの実装や例外のスローを強制しないでください。
  2. キャストは不要です。
  3. 未知のオブジェクト作成メカニズムに依存する必要はありません。
  4. 親クラスに契約に従うことや何かを実装することを要求しないでください。
  5. 最終フィールドの変更を許可します。
  6. オブジェクトの作成を完全に制御できるようにし、その中に初期化ロジックを書くことができます。

Java Cloning-Copy Constructor vs Cloning の詳細を読む

2
Naresh Joshi

コピーコンストラクターを使用して、Cloneableインターフェイスの実装やcloneメソッドの上書きなど、非常に複雑なものを使用せずにクローンを作成できます。また、ディープクローニングについて特別に心配する必要はありません。

ただし、注意すべき点は次のとおりです。

1. Cloneableを実装すると、このクラスのオブジェクトが複製可能になるのは、他のクラス/ユーザーへの刺激です。これがないと、他のクラスにはクローン可能に関する明示的な情報がない場合があります。

2.コピーコンストラクタをprivateにすると、このクラスのオブジェクトの複製を制限できます。次に、このコピーコンストラクターは、他のクラスでクローンを作成するためではなく、クラスのローカルで新しく作成されたオブジェクトを初期化するためにのみ使用できます。

3.クラスをクローン可能にしたくないが、アクセス指定子をパブリックにしてコピーコンストラクタを記述した場合、他のクラスがクラスのオブジェクトを作成できるという不安につながります。

0
Srikant M

コピーコンストラクターは、浅いクローンメカニズムと深いクローンメカニズムの両方を実装しますが、クローンコンストラクターを使用して(Cloneableインターフェイスを使用して)コピーコンストラクターを使用する主な利点は次のとおりです。

  1. Object.clone()メソッドを使用する場合、型の大文字小文字は必要ありません。
  2. Object.clone()メカニズムの場合、最終フィールドを変更またはアクセスできないのとは異なり、コピー目的で最終フィールドを変更できます。
  3. これにより、オブジェクトの作成を完全に制御できるようになり、初期化ロジックを記述できます。
  4. 他の依存クラスの参照変数を保持するクラスのオブジェクトを複製する場合、そのクラスのcloneメソッドを実装する必要はありません。コピーコンストラクタを初期化するだけで、それを実現できます。
0
BinDev