1 つ答えてください:
Java の面接で最もよく聞かれる質問の 1 つは、不変オブジェクト (不変オブジェクト) とは何ですか、不変オブジェクトの利点は何ですか、どのような状況でそれを使用する必要があるのか、さらに具体的には、なぜ Java の String クラスを に設定する必要があるのか、というものです。不変型?
不変オブジェクトは、名前が示すように、作成後に変更できないオブジェクトです。代表的な例は Java の String クラスです。
次のようにコードをコピーします。
文字列 s = "ABC";
s.toLowerCase();
上記のように、s.toLowerCase() は「ABC」の値を変更しませんが、新しい String クラス「abc」を作成し、新しいインスタンスを変数 s にポイントします。
不変オブジェクトには、可変オブジェクトに比べて多くの利点があります。
1) 不変オブジェクトにより、文字列プールの効率と安全性が向上します。オブジェクトが不変であることがわかっている場合、オブジェクトの内容をコピーする必要がある場合、オブジェクト自体をコピーする必要はなく、アドレス (通常はポインターのサイズ) をコピーするだけで済みます。非常に効率的です。この「ABC」を同時に参照する他の変数には影響しません。
2) 不変オブジェクトはマルチスレッドにとって安全です。複数のスレッドが同時に実行されている場合、変更可能オブジェクトの値は他のプロセスによって変更される可能性が高く、予測できない結果が発生するためです。また、不変オブジェクトの使用は次のとおりです。という事態は回避できます。
もちろん他にも理由はありますが、Java が String を不変に設定する最大の理由は効率と安全性です。
2 つ答えてください:
これは古いものですが、依然として人気のある質問であり、Java で文字列を不変に設計することは、次のように、メモリ、同期、データを統合する必要があります。 , 様々な理由をまとめてみます。
1. 文字列定数プールの必要性
文字列定数プール (文字列プール、文字列インターン プール、文字列保持プール) は、Java ヒープ メモリ内の特別な記憶領域です。文字列オブジェクトを作成するときに、文字列値が定数プールにすでに存在する場合、新しい文字列値は作成されません。オブジェクトですが、既存のオブジェクトへの参照です。
次のコードに示すように、実際の String オブジェクトは 1 つだけヒープ メモリに作成されます。
次のようにコードをコピーします。
文字列 s1 = "abcd";
文字列 s2 = "abcd";
概略図は次のとおりです。
文字列オブジェクトの変更を許可すると、たとえば、あるオブジェクトを変更すると別の独立したオブジェクトに影響を与えるという、さまざまな論理エラーが発生します。この定数プールの考え方は最適化手法です。
考えてください: コードが次の場合、s1 と s2 は依然として同じ実際の String オブジェクトを指しているでしょうか。
次のようにコードをコピーします。
文字列 s1= "ab" + "cd";
文字列 s2= "abc" + "d";
おそらくこの質問は初心者にとって直感に反するかもしれませんが、最新のコンパイラが定期的に最適化を実行することを考慮すると、それらはすべて定数プール内の同じオブジェクトを指すことになります。あるいは、jd-gui などのツールを使用してコンパイルされたクラス ドキュメントを表示することもできます。
2. String オブジェクトが HashCode をキャッシュできるようにする
Java の String オブジェクトのハッシュ コードは、hashMap などのコンテナーなどで頻繁に使用されます。
文字列の不変性によりハッシュ コードの一意性が保証されるため、自信を持ってキャッシュできます。これは、毎回新しいハッシュ コードを計算する必要がないことを意味します。定義には次のコードがあります。 String クラスの:
次のようにコードをコピーします。
private int hash;//ハッシュコードのキャッシュに使用されます
3. セキュリティ
ネットワーク接続アドレス URL、ファイル パス、リフレクション メカニズムに必要な文字列パラメータなど、文字列は多くの Java クラス (ライブラリ) でパラメータとして使用されます。文字列が修正されていないと、さまざまなセキュリティ リスクが発生します。
次のコードがある場合:
次のようにコードをコピーします。
ブール値接続(文字列 s){
if (!isSecure(s)) {
新しい SecurityException() をスローします。
}
// String が他の場所で変更できる場合、ここでさまざまな予期しない問題やエラーが発生します。
問題の原因;
}
一般に、String が不変である理由には、設計上の考慮事項、効率の最適化の問題、セキュリティなどが含まれます。実際、これは Java のインタビューでの多くの「理由」に対する答えでもあります。
回答 3: String クラスの不変性の利点
String は、すべての言語で最も一般的に使用されるクラスです。 Java では、String は不変であり、final であることがわかっています。 Java は実行時に String プールも保存します。これにより String が特別なクラスになります。
String クラスの不変性の利点
1. 文字列プーリングは、文字列が不変である場合にのみ可能です。文字列プールを実装すると、異なる文字列変数がプール内の同じ文字列を指すため、実行時に大量のヒープ領域を節約できます。しかし、文字列が変数の場合、文字列インターニングは不可能になります (翻訳者注: 文字列インターニングとは、異なる文字列が 1 つだけ保存されることを意味します。つまり、複数の同一の文字列は保存されません。)。その値を変更すると、この値を指す他の変数の値も変更されます。
2. 文字列が可変の場合、重大なセキュリティ上の問題が発生します。たとえば、データベースのユーザー名とパスワードは文字列として渡され、データベース接続を取得します。また、ソケット プログラミングでは、ホスト名とポートが文字列として渡されます。文字列は不変であるため、その値を変更することはできません。そうでない場合、ハッカーが抜け穴を悪用して文字列が指すオブジェクトの値を変更し、セキュリティ上の脆弱性を引き起こす可能性があります。
3. 文字列は不変であるため、マルチスレッドに対して安全であり、同じ文字列インスタンスを複数のスレッドで共有できます。これにより、スレッドの安全性の問題による同期を使用する必要がなくなります。文字列自体はスレッドセーフです。
4. クラス ローダーは文字列を使用し、不変性によりセキュリティが確保されるため、正しいクラスがロードされます。たとえば、java.sql.Connection クラスをロードする場合に、この値が myhacked.Connection に変更されると、データベースに未知の損傷が発生します。
5. 文字列は不変であるため、ハッシュコードは作成時にキャッシュされ、再計算する必要はありません。これにより、文字列はマップのキーとして非常に適しており、文字列は他のキー オブジェクトよりも高速に処理できます。 HashMap のキーに文字列が使用されることが多いのはこのためです。
上記は、文字列の不変性の利点について私がまとめたものです。