2

これは、私のプロジェクトで直面した技術的な問題のために提起されました。

問題: サード パーティのライブラリ クラス (コンテンツを変更するアクセス権がない) からプロパティ (継承) を拡張したクラスのオブジェクトを複製する必要があります。

以下の例で説明しましょう。

親クラス:

public class UnChangeableBaseClass {

  //fields and Methods

}

子クラス:

class DerivedLocalClass extends UnChangeableBaseClass implements Cloneable {

   // local fields and methods


   public Object clone(){

      Object clonedObj= null;

      try{
       clonedObj = super.clone();
      }
      catch(CloneNotSupportedException e){
        //log exceptions
      }

   }

}

これを実行しようとすると、super.clone()メソッドは Class - UnChangeableBaseClassType を参照し、メソッドをオーバーライドしませんObject clone()。私は、すべてのクラスが で拡張されていると信じています。メソッドはjava.lang.Object class暗黙的protected Object clone()にこの親クラスに継承されます。だから、派生クラスのこのメソッドが親/オブジェクトのクローンメソッドをオーバーライドするような方法で考えました。ただし、ランタイム JVM では、で明示的に定義された clone メソッドを検索しますUnChangeableBaseClass。混乱することなく適切に説明していただければ幸いです。

私の質問は次のとおりです。


  1. 親クラスにメソッドを追加してsuper.clone()Object clone メソッドを呼び出さなければならない、この典型的なケースで clone メソッドを実装するにはどうすればよいですか。

  2. 上記のケースが不可能な場合、派生クラス
    オブジェクトを複製する他の方法はありますか (上記のシナリオのすべての制限を考慮して)

  3. 最後に、この JVM の動作の理由 (上記で説明) を知りたいだけです。

4

4 に答える 4

2

JVM クローニングは、Object.clone() を探すのではなく、Marker インターフェイス Cloneable を利用することによって機能します。すべてのJavaクラスがcloneメソッドを継承することは事実ですが、Cloneableのjavadocによると

A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.

あなたの場合、Cloneable とマークされていないため、super.clone() を実行できません。親クラスを変更できない場合は、自分でコピーを作成する必要があります。

于 2012-10-25T09:13:47.670 に答える
2

親クラスにメソッドを追加して super.clone() で Object clone メソッドを呼び出すことができない、この典型的なケースで clone メソッドを実装するにはどうすればよいですか。

メソッドcloneはクラスの保護されたメソッドであるため、クラスから拡張されるため、Objectスーパークラスでもアクセスできます。したがって、基本的には、基本クラスからを使用してメソッドにアクセスできます。UnChangeableBaseClassObjectclonesuper.clone()DerivedLocalClass

上記のケースが不可能な場合、派生クラス オブジェクトを複製する他の方法はありますか (上記のシナリオのすべての制限を考慮して)

cloneメソッドを使用してオブジェクトを複製するオプションがありますが、使用しないことをお勧めします。copy-constructor派生クラスでa を使用super()し、基本クラス コンストラクターへの呼び出しを追加することをお勧めします。

また、メソッドが壊れEffective Java - Item#11 - Override clone judiciouslyていることを示唆する も参照してください。clone

この記事: -Josh Bloch on Design - Copy Constructor versus Cloningでは、次の最初の段落を参照してくださいBloch: -

私の本でクローンについての項目を読んだことがあるなら、特に行間を読んだなら、クローンが深く壊れていると私が思うことがわかるでしょう。いくつかの設計上の欠陥があります。その最大のものは、Cloneable インターフェイスに clone メソッドがないことです。つまり、単純にうまくいかないということです。何かを Cloneable にしても、それで何ができるかはわかりません。代わりに、内部で何ができるかについて何かを述べています。super.clone を繰り返し呼び出すことで Object の clone メソッドを呼び出すことになった場合、このメソッドは元のフィールドのコピーを返すことを示しています。

したがって、結論は、次のような呼び出し元のオブジェクトのコピーを返す に を含めることができるということです: copy constructor-DerivedLocalClass

public DerivedLocalClass(DerivedLocalClass obj) {
    this.setVar(obj.getVar());
}
于 2012-10-25T09:09:52.663 に答える
1

私はJava 1.7を使用していますが、OPから提供されたコードを実行しても問題はありません。スーパークラスがクローンをオーバーライドして例外をスローしない限り、スーパークラスがそれ自体をクローン可能と宣言していなくても、これは機能するはずです。

私はそれに注意します

public Object clone()

clone メソッドをオーバーライドしていないため、throws 句がありません。

于 2012-10-25T09:26:00.463 に答える
0

正しいメソッド署名は以下のとおりです

@Override
public Object clone() throws CloneNotSupportedException {
    return super.clone();
}

クローンはクラス内のProtectedメソッドでObjectあるため、クラス内でアクセスでき、クラスから拡張している場合はアクセスできます。 現在のクラスオブジェクトであるメソッドを呼び出すオブジェクトからメソッドをsuper.clone()呼び出すだけで済みます。clone()internalClonethis

   internalClone((Cloneable) this);

したがって、上記のclone()メソッド内は、呼び出されたインスタンスがそうでない場合にObjectのみスローされますCloneNotSupportedExceptionCloneable

clone メソッドに関するいくつかの誤解がある

  1. clone()メソッドはクラスprotected内にあるため、クラス外でObject呼び出すことはできません 。clone()たとえばchild.clone()、オーバーライドしてアクセスしない限りpublic
  2. Cloneableマーカーインターフェイスであり、クラスをマークしない場合、メソッドを呼び出すCloneableと取得されますCloneNotSupportedExceptionclone()
  3. クラスにプリミティブ フィールドまたは不変オブジェクトへの参照のみが含まれる場合、通常は、によって返されるオブジェクトのフィールドをsuper.clone変更する必要はありません。
  4. 慣例により、返されるオブジェクトは を呼び出して取得する必要がありますsuper.clone。クラスとそのすべてがsuperclasses (except Object)この規則に従う場合、x.clone().getClass() == x.getClass().

したがって、以下のコードは正常に動作します

public  class Child extends UnChangeableBaseClass
        implements
            Cloneable {

    int index = 0;

    public Child(int index) {

        this.index = 10;
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

参考文献:

  1. オブジェクト#クローン()
  2. クローン可能
于 2012-10-25T09:12:01.057 に答える