回答:
クローンが保護されているという事実は非常に疑わしいです- clone
メソッドがCloneable
インターフェースで宣言されていないという事実もそうです。
ので、それはデータのコピーを取るための方法はかなり無用になり、あなたが言うことができません。
if(a instanceof Cloneable) {
copy = ((Cloneable) a).clone();
}
のデザインCloneable
は今では間違いとみなされていると思います(下記引用)。私は通常、インターフェースの実装を作成できるようにしたいと思いますCloneable
が、必ずしもインターフェースを作成する必要はありませんCloneable
(の使用に似ていますSerializable
)。これは反射なしでは実行できません。
ISomething i = ...
if (i instanceof Cloneable) {
//DAMN! I Need to know about ISomethingImpl! Unless...
copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}
Josh Blochの効果的なJavaからの引用:
「Cloneableインターフェースは、オブジェクトがクローニングを許可することを宣伝するためのミックスインインターフェースとして意図されていました。残念ながら、この目的を果たすことができません...これは非常に非典型的なインターフェースの使用であり、エミュレートされるものではありません。 ...インターフェイスを実装してクラスに何らかの影響を与えるためには、インターフェイスとそのすべてのスーパークラスが、かなり複雑で、実施不可能で、ほとんど文書化されていないプロトコルに従う必要があります。
Serializable
実装するかどうかは実装次第Serializable
です。私はこれを拡張していましたCloneable
-それはインターフェースが拡張すべきものではありません-しかし、インターフェースの実装は自由Cloneable
です。問題は、インターフェースタイプのパラメーターがある場合、それが複製可能かどうかを尋ねることです。しかし、実際にはそれを複製することはできません!
Clonableインターフェースは、クラスがクローンをサポートできることを示す単なるマーカーです。このメソッドはオブジェクトで呼び出さないように保護されています。パブリックとしてオーバーライドできます(オーバーライドする必要があります)。
太陽から:
Objectクラスでは、clone()メソッドは保護されていると宣言されています。Cloneableを実装するだけの場合、同じパッケージのサブクラスとメンバーのみがオブジェクトでclone()を呼び出すことができます。任意のパッケージ内の任意のクラスがclone()メソッドにアクセスできるようにするには、以下のように、それをオーバーライドしてパブリックとして宣言する必要があります。(メソッドをオーバーライドすると、プライベートを少なくできますが、プライベートを高くすることはできません。ここでは、Objectのprotected clone()メソッドがパブリックメソッドとしてオーバーライドされています。)
Set
clone
これは、現在のクラスに固有になるようにオーバーライドする必要があるため、保護されています。clone
オブジェクトをまったく複製するpublic メソッドを作成することは可能ですが、これは、それを必要とするクラス用に特別に作成されたメソッドほど良くありません。
Cloneメソッドは、どのオブジェクトに対しても直接使用することはできません。そのため、サブクラスによってオーバーライドされることを意図しています。
もちろん、それは公開される可能性があり、クローニングが不可能な場合は適切な例外をスローするだけですが、それは誤解を招くだろうと思います。
クローンの実装方法では、クローンを使用する理由と、オブジェクトのクローンを作成する方法について考えます。
デフォルトの実装は、すべてのフィールド(privateを含む)の浅いメンバーごとのコピーを行い、コンストラクターを回避するため、保護されています。これは、オブジェクトが最初に処理するように設計されているものではありません(たとえば、作成されたオブジェクトインスタンスを共有リストなどで追跡する場合があります)。
同じ理由で、のデフォルトの実装はclone()
、呼び出されたオブジェクトがを実装していない場合にスローされCloneable
ます。これは潜在的に安全ではない操作であり、広範囲に影響を与えるため、クラスの作成者は明示的にオプトインする必要があります。
cloneableのjavadocから。
* By convention, classes that implement this interface (cloneable) should override
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.
* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface. Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.
したがって、すべてのオブジェクトでcloneを呼び出すことができますが、これはほとんどの場合、必要な結果や例外ではありません。ただし、クローン可能を実装する場合にのみ推奨されます。
私見それはこれと同じくらい簡単です:
#clone
クローンできないオブジェクトでは呼び出さないでください。したがって、公開されません#clone
Object
適切なクラスの浅いコピーを取得するには、Cloneableを実装するサブクラスobから呼び出す必要があります他のクラスではなく、サブクラスから呼び出すことができるメソッドの適切なスコープは何ですか?
ですprotected
。
Cloneable
もちろん、実装するクラスはこのメソッドをパブリックにするので、他のクラスから呼び出すことができます。
Clone()メソッドには、内部的に「Cloneableのインスタンスかどうか」のチェックがあります。これは、Javaチームがclone()メソッドの不適切な使用を制限すると考えられる方法です。clone()メソッドは保護されています。つまり、サブクラスのみによってアクセスされます。オブジェクトはすべてのサブクラスの親クラスであるため、上記の「Cloneableのインスタンス」のチェックを行わなければ、Clone()メソッドはすべてのクラスでそのまま使用できます。これが、Javaチームがclone()メソッドに「Cloneableのインスタンスかどうか」をチェックさせることで、clone()の不適切な使用を制限しようと考えた理由です。
したがって、cloneableを実装するクラスは、Objectクラスのclone()メソッドを使用できます。
また、保護されているため、複製可能なインターフェースを実装するサブクラスのみが使用できます。パブリックにしたい場合は、このメソッドを独自に実装したサブクラスでオーバーライドする必要があります。
はい、私が会った同じ問題。しかし、私はこのコードを実装することでそれを解決します
public class Side implements Cloneable {
public Side clone() {
Side side = null;
try {
side = (Side) super.clone();
} catch (CloneNotSupportedException e) {
System.err.println(e);
}
return side;
}
}
以前と同じように誰かが言った。
まあ、太陽の開発者も人間だけであり、実際にはクローンメソッドを保護されたものとして実装するのに大きな間違いを犯しました。これは、機能しないクローンメソッドをArrayListに実装したのと同じ間違いです!そのため、一般に、クローンメソッドについては、経験豊富なJavaプログラマでさえも、より深い誤解があります。
ただし、私は最近、オブジェクトがどのように構築され、何が含まれているかに関係なく、オブジェクトとそのすべてのコンテンツをコピーするための高速で簡単なソリューションを見つけました。ここで私の答えを参照してください:Object.clone()の使用におけるバグ
繰り返しますが、Java JDKフレームワークは見事な考え方を示しています。
クローン可能なインターフェースには、「public T clone();」が含まれていません。これは、インスタンスを複製できる属性(Serializableなど)のように機能するためです。
このデザインには何も問題はありません。
Object.clone()は、カスタム定義クラスで必要なことを行いません。
MyclassがCloneable =>を実装している場合、「public MyClass clone()」でclone()を上書きします
MyInterfaceがCloneableを拡張し、一部のMyClassesがMyInterfaceを実装している場合: "public MyInterface clone();"を定義するだけです。インターフェースでは、MyInterfaceオブジェクトを使用するすべてのメソッドは、それらのMyClassクラスに関係なく、それらを複製できます。