1. ホーム
  2. java

[解決済み] なぜCloneableは非推奨なのですか?

2022-05-18 06:58:48

質問

一般に、次のように理解されています。 Cloneable インターフェースは壊れていると理解されています。これには多くの理由がありますが、ここでは触れません。 その他 がすでにやってくれました。の立場でもあります。 Javaアーキテクト の立場そのものです。

私の質問は、なぜまだ非推奨にされていないのか、ということです。もしコア Java チームが壊れていると判断したのであれば、非推奨も考慮されているはずです。そうしない理由は何でしょうか (Java 8 では はまだ非推奨です。 )?

どのように解決するのですか?

あるところに バグ に 1997 年に提出された Java バグデータベース を追加したことについて clone() メソッドを Cloneable に変更し、無駄をなくしました。これは、解決策 "won't fix" で閉じられ、正当性は次のとおりでした。

Sun の技術検討委員会 (TRC) はこの問題を詳細に検討し、次のように勧告しました。 を取ることを推奨しました。 を改善する以外の行動をとることを推奨しました。 現在の Cloneable インターフェイスのドキュメントを改善する以外の . 以下は、勧告の全文です。 勧告の全文です。

既存のJavaオブジェクトクローンAPIには問題がある。 java.lang.Objectに java.lang.Objectにprotected "clone"メソッドがあり、インターフェイスがあります。 java.lang.Cloneableがあります。 その意図は、もしあるクラスが他の人にそのクラスのクローンを作らせたいのであれば クラスが他の人にクローンすることを望むなら、Cloneableインターフェイスをサポートし、デフォルトのprotected cloneableをオーバーライドしなければなりません。 インターフェイスをサポートし、デフォルトの protected clone メソッドを public clone メソッドで上書きすることです。 残念ながら、都合よく時の流れの中で失われてしまった理由のために Cloneable インターフェースは clone メソッドを定義していません。 メソッドを定義していません。

この組み合わせはかなりの量の混乱を招きます。 いくつかのクラスは はCloneableをサポートすると主張しますが、誤ってcloneメソッドをサポートすることを忘れてしまいます。 clone メソッドをサポートしていないクラスがあります。 開発者は、Cloneable がどのように動作することになっているのか、そして clone が何をすることになっているのかについて混乱しています。 開発者は、Cloneable がどのように動作し、clone が何を行うことになっているのかについて混乱しています。

残念ながら、Cloneable に "clone" メソッドを追加することは、互換性のない変更になります。 互換性のない変更です。 バイナリの互換性は壊れませんが、ソースの互換性は壊れます。 ソースの互換性は失われます。 事例として、実際には 実際には、クラスが Cloneable インターフェースをサポートしているにもかかわらず、パブリックな clone メソッドを提供できていないクラスが、実際には数多く存在することを示す逸話があります。 議論の結果 議論した結果、TRC は満場一致で、互換性を保つために既存の 互換性に影響を与えるため、既存の Cloneable インターフェースを修正しないことを満場一致で推奨しました。

代替案として、新しいインターフェイス java.lang.PubliclyCloneable を追加して、Cloneable の本来の意図された目的を反映させることです。 を追加することでした。 5 対 2 の多数決で、TRC はこれに反対を推奨しました。 主な懸念は、これがさらに多くの混乱(スペルの混乱を含む!)を追加することになるということでした。 スペルの混乱も!)、すでに混乱している図式にさらに混乱を加えることになるということです。

TRC は満場一致で、既存の Cloneable インターフェイスに追加のドキュメントを追加することを推奨しました。 既存の Cloneable インターフェイスに追加のドキュメントを追加することを推奨します。 をよりよく説明するために どのように使用されることを意図しているか、そして実装者のための "ベストプラクティス" を記述するために、既存の Cloneable インターフェイス を説明することです。

ということで、これは直接的には関係ないのですが 非推奨 を非推奨としない理由は、Technical Review Comitee の判断によります。 既存のドキュメントを修正することで十分である を決定したからです。そして、そうしたのです。Java 1.4 までは。 Cloneable は次のように文書化されていました。

クラスは Cloneable インターフェースを実装しており、そのインターフェイスは Object.clone()メソッドに、そのメソッドがそのクラスのインスタンスのフィールド間のコピーを作成することが合法であることを示すために、Cloneableインターフェイスを実装します。 メソッドに対して、そのクラスのインスタンスをフィールドごとにコピーすることが合法であることを示します。

Cloneableインターフェイスを実装していないインスタンスを複製しようとすると、例外CloneNothing! インターフェイスを実装していないインスタンスを複製しようとすると、例外 CloneNotSupportedException がスローされます。 が投げられます。

Cloneable インターフェースはメソッドを宣言していません。

2002年2月にリリースされたJava 1.4以降、現行版(Java 8)までは、以下のようになります。

<ブロッククオート

クラスはCloneableインターフェイスを実装しており、そのインターフェイスは Object.clone()メソッドに、そのメソッドがインスタンスのフィールドごとのコピーを作成することが合法であることを示すために、Cloneableインターフェイスを実装します。 メソッドに対して、そのクラスのインスタンスをフィールドごとにコピーすることが合法であることを示します。 Objectの を実装していないインスタンスに対して、Object.clone() メソッドを呼び出すと、例外CloneNothing() が発生します。 インターフェイスを実装していないインスタンスに対して Object の clone メソッドを呼び出すと、例外 CloneNotSupportedException がスローされます。 がスローされます。

慣習として、このインタフェースを実装するクラスは、(protected である)Object.clone を public メソッドでオーバーライドしなければなりません。 Object.clone (protected) をパブリックメソッドでオーバーライドする必要があります。このメソッドのオーバーライドの詳細については Object.clone()を参照してください。

このインタフェースはcloneメソッドを含んでいないことに注意してください。そのため このインターフェイスを実装しているという事実だけで、オブジェクトを複製することはできません。 このインターフェイスを実装しているという事実だけでは、オブジェクトのクローンを作ることはできません。たとえcloneメソッドを反射的に呼び出したとしても を反射的に呼び出したとしても、それが成功する保証はない。