ホームページ  >  記事  >  Java  >  Java の String クラスが不変である理由 (詳細な説明)

Java の String クラスが不変である理由 (詳細な説明)

烟雨青岚
烟雨青岚転載
2020-06-24 13:27:146548ブラウズ

Java の String クラスが不変である理由 (詳細な説明)

Java の String クラスが不変である理由 (詳細な説明)

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];}

String クラスの値は次のとおりです。値配列に格納され、プライベートfinal

1によって変更されます。プライベート変更は、外部クラスが値にアクセスできず、サブクラスが値にアクセスできないことを示します。もちろん、String クラスはサブクラスを持つことができません。クラスは最終変更
2、最終変更です。値の参照は変更されず、値は String のコンストラクターでのみ初期化され、配列内の値を変更する他の方法はありません。値が保証するものであることを示します。 value の参照と値は変更されないということです。

したがって、String クラスは不変であると言います。

また、substring などの多くのメソッドは、元の String クラスでは動作せず、新しい String クラスを生成します。

public String substring(int beginIndex) {
	if (beginIndex < 0) {
		throw new StringIndexOutOfBoundsException(beginIndex);
	}
	int subLen = value.length - beginIndex;
	if (subLen < 0) {
		throw new StringIndexOutOfBoundsException(subLen);
	}
	return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);}

String が無効に設定されているのはなぜですか?変化?

#文字列定数プール

Java には 8 つの基本データ型があります

整数型: byte、short、int、long。パッケージ化タイプは、Byte、Short、Integer、Long
浮動小数点タイプ: float、double です。パッケージ化タイプは Float、Double
Character type: char です。パッケージ化タイプは文字
ブール型: booleanです。パッケージング タイプは Boolean

8 つのパッケージング タイプのうち、Float と Double を除き、定数プールは実装されていません。残りは実装されています。もちろん、これらはすべてフライウェイト モードで実装された String クラスの定数です。プールは JVM レベルで実装されます。

なぜ定数プールがあるのでしょうか?

定数プールは、システムのパフォーマンスに影響を与えるオブジェクトの頻繁な作成と破棄を回避するために使用され、オブジェクト共有を実装します。

たとえば、文字列定数プールは、コンパイル段階ですべての文字列リテラルを定数プールに置きます。

メモリ スペースの節約: 定数プール内のすべての同一の文字列定数はマージされ、1 つのスペースのみを占有します。
  • 実行時間を節約する: 文字列を比較する場合、== は、equals() よりも高速です。 2 つの参照変数の場合、== を使用して参照が等しいかどうかを判断するだけでなく、実際の値が等しいかどうかも判断できます。
  • 文字列定数プールはどこですか?

jdk1.7 より前のことについては説明しません。jdk1.7 から文字列定数プールがヒープに配置されるようになり、この記事の内容はすべて jdk1 に基づいています。 8

次のコードはよく質問されます

String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
String str4 = new String("abc");
// trueSystem.out.println(str1 == str2);
// falseSystem.out.println(str1 == str3);
// falseSystem.out.println(str3 == str4);

メモリ内の構造は次のとおりです


定数プールには参照が格納されますJava の String クラスが不変である理由 (詳細な説明)
上記のコードの出力について説明します。Java で文字列オブジェクトを作成するには 2 つの方法があります

String str1 = "abc";
String str2 = "abc";
// trueSystem.out.println(str1 == str2);

リテラル値を使用して文字列を作成する場合、JVM はまず文字列を削除しますオブジェクト「abc」がプールに存在するかどうかを確認します。

存在しない場合は、文字列プールにオブジェクト「abc」を作成し、プール内のオブジェクト「abc」のアドレスを str1 に割り当てます。 、そのため、 str1 は、プール内の文字列オブジェクト "abc" を指します。

それが存在する場合、オブジェクトは作成されず、プール内の "abc" オブジェクトのアドレスが直接返され、 str2に割り当てられます。 str1 と str2 は同じ文字列プール内の「abc」オブジェクトを指しているため、結果は true になります。

String str3 = new String("abc");
String str4 = new String("abc");
// falseSystem.out.println(str3 == str4);

new キーワードを使用して文字列オブジェクトを作成する場合、JVM はまず文字列プール内で文字列オブジェクト "abc" を検索します。

そうでない場合は、まず文字列オブジェクトを検索します。文字列プール。プール内に「abc」文字列オブジェクトを作成し、次にヒープ内に「abc」文字列オブジェクトを作成し、ヒープ内の「abc」文字列オブジェクトのアドレスを str3

に割り当てます。存在する場合は、プールに "abc" オブジェクトを作成する代わりに、ヒープ内に直接 "abc" 文字列オブジェクトを作成し、ヒープ内の "abc" オブジェクトのアドレスを str4 に割り当てます。このように、str4 はヒープ内に作成された "abc" 文字列オブジェクトを指します。

str3 と str4 は異なる文字列オブジェクトを指しているため、結果は false になります。

キャッシュ ハッシュコード

String クラスは不変であるため、String クラスが作成されると、ハッシュコードはハッシュ メンバー変数にキャッシュされます。ハッシュコードは変わりません。こうすることで、ハッシュコードを使いたいときに毎回再計算することなく直接取得できるので効率が上がります。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {

    /** Cache the hash code for the string */
    private int hash; // Default to 0
	}

HashMapのキーとして利用可能

String クラスの不変性により、HashMap のキーとして使用されることが多く、String クラスが可変で内容が変わると hashCode も変わります。このキーに基づいて HashMap から取得すると、値が取得されないか、間違った値が取得される可能性があります

スレッド セーフティ

不変オブジェクト本質的にスレッドセーフであるため、マルチスレッド環境での問題を回避できます。 次に、String に対して同期操作を実行します。

読んでくれた皆さんに感謝します。多くの利益を得られることを願っています。

この記事は、https://blog.csdn.net/zzti_erlie/article/details/106872673

から転載されたものです:「java チュートリアル

以上がJava の String クラスが不変である理由 (詳細な説明)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。