ホームページ >Java >&#&チュートリアル >Java の String 文字列の詳細な紹介

Java の String 文字列の詳細な紹介

黄舟
黄舟オリジナル
2017-08-11 09:45:031277ブラウズ

以下のエディターは、Java String 文字列に関する決まり文句を提供します (必読の記事)。編集者はこれがとても良いものだと思ったので、皆さんの参考として今から共有します。エディターに従って見てみましょう

Java での文字列オブジェクトの作成には 2 つの形式があります。1 つは String str = "hello"; などのリテラル形式で、もう 1 つは new のような標準コンストラクター オブジェクトを使用するものです。 . String str = new String("hello"); などのメソッド

この常識については詳しく説明しません。

まず、String クラスは Final クラスですが、なぜ Final 形式で定義されているのでしょうか。

簡単に言うと、このような頻繁に使用されるデータ型について、設計者は、設計が十分であり、継承する必要がないと考えています。そうでない場合、ランダムな継承や書き換えによってプログラムのパフォーマンスが低下する可能性があります。

タイトルにあるように、詳細な内容なので、JVM レベルでの String の小さなアクションを掘り下げてみましょう。

最初にリテラル作成の形式について説明します:

文字列オブジェクトを作成するコードにリテラル形式が現れると、JVM はまずリテラルをチェックして、文字列内に同じ内容の文字があるかどうかを確認します。定数プール 文字列オブジェクトへの参照がある場合は、この参照が返されます。そうでない場合は、新しい文字列オブジェクトが作成され、この参照が文字列定数プールに入れられて、参照が返されます。

以下に示すように:


String str1 = "hello" ;

最初に作成したとき、hello という内容のオブジェクトは存在しないと考えていました。 JVM は、文字列定数プールを通じて hello という内容の文字列オブジェクトの存在を見つけることができません。その後、文字列オブジェクトを作成し、新しく作成したオブジェクトの参照を文字列定数プールに入れて、変数への参照を返します。 str1

次にそのようなコードがある場合


String str2 = "hello" ;

同様に、JVM はこのリテラルを検出する必要があります。JVM は文字列定数プールを検索し、「hello」という内容を持つ文字列オブジェクトを見つけます。 " が存在するため、すでに存在します。文字列オブジェクトへの参照が変数 str2 に返されます。ここでは新しい文字列オブジェクトが再作成されないことに注意してください。

str1 と str2 が同じオブジェクトを指しているかどうかを確認します。このコードを使用できます


System.out.println(str1 == str2);

結果は true です。

2 番目のタイプは new を使用して作成されます:


String str3 = new String("hello");

new を使用して文字列オブジェクトを構築する場合、文字列定数プール内に同じ内容を持つオブジェクトへの参照があるかどうかは関係ありません。 、新しい String オブジェクトが作成されます。したがって、次のコードを使用してテストします。


String str3 = new String("hello");
System.out.println(str1 == str3);

結果は false です。これら 2 つの参照が異なるオブジェクトを指していることを示します。

intern

上記の new を使用して作成された文字列オブジェクトについて、このオブジェクトの参照を文字列定数プールに追加したい場合は、intern メソッドを使用できます。

intern を呼び出した後、まず文字列定数プールにオブジェクトへの参照があるかどうかを確認し、存在する場合はその参照を変数に返します。


String str4 = str3.intern();
System.out.println(str4 == str1);

結果は真実です。

質問

前提条件はありますか?

文字列定数プールの実装の前提条件は、Java の String オブジェクトが不変であることです。これにより、複数の変数が同じオブジェクトを安全に共有できます。 Java の String オブジェクトが可変であり、参照操作によってオブジェクトの値が変更される場合、他の変数も影響を受けることは明らかです。

参照またはオブジェクト

文字列定数プールに格納されるのが参照であってもオブジェクトであっても、この問題は最も一般的です。文字列定数プールには、オブジェクトではなくオブジェクト参照が格納されます。 Java では、オブジェクトはヒープ メモリに作成されます。文字列定数プールはヒープメモリの永続世代に存在します

メリットとデメリット

文字列定数プールの利点は、同じ内容の文字列の作成を減らし、メモリスペースを節約できることです。

あえて欠点について話すとすれば、スペースと引き換えに CPU の計算時間が犠牲になるということです。 CPU の計算時間は主に、文字列定数プール内に同じ内容のオブジェクトへの参照があるかどうかを確認するために使用されます。ただし、内部実装はHashTableなので計算コストは​​低いです。

GCリサイクル?

文字列定数プールには共有文字列オブジェクトへの参照が保持されているため、これらのオブジェクトはリサイクルできないということですか?

まず第一に、質問で共有されるオブジェクトは一般に比較的小さいです。私の知る限り、この問題は以前のバージョンにも存在していましたが、弱参照の導入により、この問題は現在では解消されているはずです。

インターン利用?

关于使用intern的前提就是你清楚自己确实需要使用。比如,我们这里有一份上百万的记录,其中记录的某个值多次为美国加利福尼亚州,我们不想创建上百万条这样的字符串对象,我们可以使用intern只在内存中保留一份即可。

总有例外?

你知道下面的代码,会创建几个字符串对象,在字符串常量池中保存几个引用么?


String test = "a" + "b" + "c";

答案是只创建了一个对象,在常量池中也只保存一个引用。我们使用javap反编译看一下即可得知。

实际上在编译期间,已经将这三个字面量合成了一个。这样做实际上是一种优化,避免了创建多余的字符串对象,也没有发生字符串拼接问题。

以上がJava の String 文字列の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。