以前は、コレクションを安全にコピーすると次のようなことをするように言っていました。
public static void doThing(List<String> strs) {
List<String> newStrs = new ArrayList<>(strs);
または
public static void doThing(NavigableSet<String> strs) {
NavigableSet<String> newStrs = new TreeSet<>(strs);
しかし、これらの「コピー」コンストラクター、同様の静的作成メソッドおよびストリームは本当に安全で、ルールはどこに指定されていますか?安全とは、Java言語によって提供される基本的なセマンティック整合性の保証と、悪意のある呼び出し元に対して適用されるコレクションSecurityManager
であり、妥当な手段でバックアップされ、欠陥がないことを前提としています。
私はこの方法を投げると幸せConcurrentModificationException
、NullPointerException
、IllegalArgumentException
、ClassCastException
、など、またはおそらくハング。
String
不変の型引数の例として選択しました。この質問については、私は独自の落とし穴を持つ変更可能な型のコレクションのディープコピーには興味がありません。
(明確にするために、私はOpenJDKのソースコードを見て、とに対して何らかの回答をArrayList
しましたTreeSet
。)
NavigableSet
他のComparable
ベースのコレクションは、クラスがcompareTo()
正しく実装されていないことを検出して例外をスローすることがあります。信頼できない議論によってあなたが何を意味するかは少し不明確です。悪人が悪い文字列のコレクションを作成し、それらをコレクションにコピーすると、何か悪いことが起こりますか?いいえ、コレクションフレームワークはかなりしっかりしていて、1.2から存在しています。
HashSet
(そして、一般に他のすべてのハッシュコレクション)はhashCode
、要素の実装の正確性/完全性に依存しており、TreeSet
それにPriorityQueue
依存していますComparator
(そして、カスタムコンパレータがある場合はそれを受け入れずに同等のコピーを作成します)、コンパイル後に検証されないEnumSet
特定のenum
型の整合性を信頼するため、生成javac
または手作りされていないクラスファイルがそれを覆す可能性があります。
new TreeSet<>(strs)
でstrs
は、どこにがありNavigableSet
ますか?結果TreeSet
はソースのコンパレータを使用するため、これは一括コピーではありません。これは、セマンティクスを保持するためにも必要です。含まれている要素を処理するだけで問題がなければtoArray()
、次の方法です。反復順序も保持します。「要素の取得、要素の検証、要素の使用」で問題がなければ、コピーを作成する必要さえありません。問題は、すべての要素を検証するときに始まり、その後すべての要素を使用します。次に、TreeSet
カスタムコンパレータ付きのコピーを信頼することはできません
checkcast
各要素に対してaの効果を持つ唯一の一括コピー操作はtoArray
、特定のタイプを使用したものです。私たちは常にそれで終わります。ジェネリックコレクションは実際の要素の型さえも知らないため、コピーコンストラクターは同様の機能を提供できません。もちろん、チェックはいつでも延期することができますが、質問の目的がわかりません。要素を使用する直前にチェックして失敗することに問題がなければ、「セマンティックインテグリティ」は必要ありません。