これは、上記の回答で既に言及されている2つの理由を概説する素晴らしい記事です。
- セキュリティ: システムは、変更されることを心配することなく、読み取り専用情報の機密ビットを配布できます
- パフォーマンス: 不変データは、スレッドセーフにするのに非常に役立ちます。
そして、これはおそらくその記事の中で最も詳細なコメントです。これは、Java の文字列プールとセキュリティの問題に関係しています。文字列プールに入れるものを決定する方法についてです。文字のシーケンスが同じである場合に両方の文字列が等しいと仮定すると、誰が最初にそこに到達するかという競合状態とそれに伴うセキュリティの問題があります。そうでない場合、文字列プールには冗長な文字列が含まれるため、最初にそれを持つ利点が失われます。自分で読んでみませんか?
String を拡張すると、equals と intern に大混乱が生じます。JavaDoc は等しいと言います:
この文字列を指定されたオブジェクトと比較します。引数が null ではなく、このオブジェクトと同じ文字シーケンスを表す String オブジェクトである場合にのみ、結果は true になります。
java.lang.Stringfinal ではないと仮定すると、 aSafeStringは a と等しくなる可能性がStringあり、その逆も成り立ちます。これらは同じ文字列を表すためです。
--に申し込んだ場合intern、JVM の文字列プールに入りますか? 保持されている参照先およびすべてのオブジェクトは、JVM の存続期間中その場でロックされます。一連の文字を最初にインターンするのは誰になるかについて競合状態が発生します。おそらくあなたが勝つか、 a 、または別のクラスローダー (したがって別のクラス) によってロードされる a かもしれません。SafeStringSafeStringClassLoaderSafeStringSafeStringStringSafeString
プールへの競争に勝った場合、これは真のシングルトンとなり、人々はリフレクションとsecretKey.intern().getClass().getClassLoader().
または、JVM は、具体的な String オブジェクトのみ (およびサブクラスなし) がプールに追加されるようにすることで、この穴を塞ぐことができます。
SafeStringequals が!= Stringthen SafeString.intern!=String.internのように実装されている場合SafeString、プールに追加する必要があります。プールは<Class, String>代わりにのプールになり、プール<String>に入る必要があるのは新しいクラスローダーだけです。