12

昔々、クラスがありました:

public class Scope<C extends Cloneable & Comparable<C>> implements Comparable<Scope<C>>, Cloneable, Serializable {

   private C starts;
   private C ends;
   ...

   @SuppressWarnings("unchecked")
   @Override
   public Object clone() {
       Scope<C> scope;
       try {
           scope = (Scope<C>) super.clone();
           scope.setStarts((C) starts.clone()); // The method clone() from the type Object is not visible
           scope.setEnds((C) ends.clone()); // The method clone() from the type Object is not visible
       } catch (CloneNotSupportedException e) {
           throw new RuntimeException("Clone not supported");
       }
       return scope;
   }
}

オブジェクトには次のものがあります。

protected native Object clone() throws CloneNotSupportedException;

そして、クローン可能なインターフェースは次のとおりです。

public interface Cloneable { 
}

これをどのように複製すればよいですか?

4

6 に答える 6

12

解決

JavaDeep-Cloningライブラリを使用します。

クローン作成ライブラリは、オブジェクトをディープクローンする小さなオープンソース(Apacheライセンス)のJavaライブラリです。オブジェクトは、Cloneableインターフェースを実装する必要はありません。事実上、このライブラリは任意のJavaオブジェクトのクローンを作成できます。つまり、キャッシュされたオブジェクトを変更したくない場合や、オブジェクトのディープコピーを作成したい場合は、キャッシュの実装で使用できます。

Cloner cloner=new Cloner();
XX clone = cloner.deepClone(someObjectOfTypeXX);

補遺

以前の回答には次の欠点がありました。

  • それは多くのコードを追加します
  • コピーするすべてのフィールドをリストして、これを行う必要があります
  • clone();を使用する場合、これはリストでは機能しません。clone()for HashMapnotes:このインスタンスの浅いコピーを返しますHashMap。キーと値自体は複製されないため、手動で行うことになります。

Serializableどこにでも追加する必要があるかもしれないので、シリアル化も悪いです。

于 2009-08-07T06:02:03.083 に答える
5

これが、誰も好きCloneableではない理由の1つです。Cloneableマーカーインターフェイスであるはずですが、反射なしでは任意のオブジェクトのクローンを作成できないため、基本的には役に立ちません。

これを行うためのほとんど唯一の方法は、パブリック メソッドを使用して独自のインターフェイスを作成することですclone()( ""と呼ばれる必要はありませんclone())。これは、別のStackOverflowの質問の例です。

于 2009-04-29T19:51:48.470 に答える
4

うまくいけば、Javaでの汎用クローン作成の問題を解決しました。

public class Generic<T> {
  private T data;

  public Generic() {
    // ...
  }

  @SuppressWarnings("unchecked")
  @Override
  public Object clone() {
    Generic<T> cloned = new Generic<T>();
    try {
      cloned.data = (T) data.getClass().getMethod("clone").invoke(data);
    } catch (Exception e) {
      // ...
    }
    return cloned;
  }
}
于 2013-02-11T08:27:50.107 に答える
2

少しOTですが、これで将来の多くの悲しみを救うことができます:

   catch (CloneNotSupportedException e) {
       throw new RuntimeException("Clone not supported", e);
   }

そのため、スタックトレースを取得すると、問題の原因となったオブジェクトがわかります。

コアの質問に答えるために、mmyersが書いたようにパブリックclone()を実装し、Cがそれを拡張することを要求する独自のインターフェース。

于 2009-04-29T20:31:40.933 に答える
1

一般的なコメントとして、可能な限りObject.clone()の使用は避けてください。問題のコードを制御できる場合は、代わりにコピーコンストラクターを実装してください。詳細については、こちらをご覧ください。

于 2009-04-29T20:44:31.340 に答える
-1

Cloneableご覧のとおり、クラスが実装を試み、ディープクローンが必要な場合は、すべての構成オブジェクトが不変、プリミティブであるか、クローン可能である必要があります。

多くの場合、より適切で簡単なアプローチは、コピーコンストラクターを作成することです。

public class Scope<C extends Comparable<C>> implements Comparable<Scope<C>>, Serializable {
    private C starts;
    private C ends;
    public Scope(final Scope original) {
       starts = new C(original.starts);
       ends = new C(original.ends);
       // initialize all my other fields from "original"
    }
}

Cそしてもちろん、ポリモーフィズムを処理できるコピーコンストラクターが必要です。

ソースをに変更するためのアクセスまたは機能がない場合C、コピーの方法は、その方法に関係なく、非常に困難であり、潜在的に不可能です。たとえば、enumインスタンスのコピーを作成することはできません。

于 2009-04-29T19:57:59.780 に答える