为什么说String的拼接会产生很多的无用对象呢?eg.String str = "";while(true){
str +="abc";
}
按我的理解,字符串拼接只会在常量池中创建共享对象,常量池的对象会被垃圾回收器回收吗?为什么说会产生很多无用的对象,需要垃圾回收,从而影响程序性能呢?
拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...
投稿者が言ったことに関して、文字列のスプライシングは定数プールに共有オブジェクトのみを作成します。それが具体的に何を意味するのかはわかりませんが、この書き方がなぜ無駄なオブジェクトを大量に生成するのかは説明できます。投稿者に役立ちました。
答えは次のとおりです:
まず上の図を見てください。JDK の String クラスは Final クラスであり、String 文字を格納するために使用される値も Final です。
これは、文字列オブジェクトの作成後にその値を変更できないことを意味します。したがって、各ループによって生成される文字列は、新しい String オブジェクトである必要があります。しかし、上記のコードはあなたが思っているよりも多くのオブジェクトを生成します。 どうぞ写真を見てください!
----------美しい分割線--------------- --- ---
2番目の写真の赤いボックスは、最初の写真の赤いボックスの逆コンパイルされたコードです。画像からわかります: a+=a は次のことを行います:
Call String.valueOf(a)。 a も文字列であるため、このステップでは新しいオブジェクトは生成されません。
新しい StringBulid (最初のオブジェクトは実際には文字列 a)、このステップでは Stringbuild オブジェクトが生成されます。
.append (追加された文字列)
.toString()、このステップは Stringbuild の toString メソッドを呼び出します。
Stringbuild の toString() ソース コードをもう一度見てみましょう
おっと!別の String オブジェクトが作成されるのはなぜですか?
a+=a の分析はここで完了しているため、ループ内のすべての文字列追加操作により、実際には少なくとも 1 つの StringBuild オブジェクトと 1 つの String オブジェクトが作成されます。
String は不変オブジェクトであるため、String 型を変更するたびに、実際には新しい String オブジェクトを生成し、新しい String オブジェクトへのポインタを指すのと同じことになるため、頻繁に変更される文字列は使用しないことをお勧めします。オブジェクトが生成されるたびに、特にメモリ内に参照されていないオブジェクトが多すぎると、JVM の GC が動作し始め、速度が大幅に低下するため、String を使用します。 。
頻繁に変更される変数には StringBuffer を使用する必要があります~
... jdk1.8 以降のみ、文字列の複数の連結に StringBuild を使用できます。 。旧バージョンはこうじゃない! ~~前回記事を読んだのですが、何か間違っているのかわかりません。 1.8 より前では、String を複数回変更する必要がある場合は、StringBuffer または StringBuilder を使用する必要があります。 1.8 では糖衣構文が有効になり、この領域が変更されたため、明示的に StringBuilder を呼び出さなくても高い効率を享受できるようになりました。
文字列の場合は、定数プールに共有オブジェクトのみを作成します。
ここで作成されたオブジェクトはすべて役に立たないオブジェクトではないでしょうか?最終結果に加えて、GC のリサイクルにも時間がかかります。
string は char[] の最終的な変更であるため、毎回新しいオブジェクトを作成する必要があります StringBuilder が非常に効率的である理由は、通常は演算の追加によって、容量がいっぱいになった場合にのみ配列が動的に拡張されるためです。要約すると、stringbuilder はオブジェクトの生成を減らし、毎回新しいオブジェクトを生成する必要がありません。専門家にアドバイスを求めてください。 ~! ~! ~
投稿者が言ったことに関して、文字列のスプライシングは定数プールに共有オブジェクトのみを作成します。それが具体的に何を意味するのかはわかりませんが、この書き方がなぜ無駄なオブジェクトを大量に生成するのかは説明できます。投稿者に役立ちました。
答えは次のとおりです:
まず上の図を見てください。JDK の String クラスは Final クラスであり、String 文字を格納するために使用される値も Final です。
これは、文字列オブジェクトの作成後にその値を変更できないことを意味します。したがって、各ループによって生成される文字列は、新しい String オブジェクトである必要があります。しかし、上記のコードはあなたが思っているよりも多くのオブジェクトを生成します。 どうぞ写真を見てください!
----------美しい分割線--------------- --- ---
2番目の写真の赤いボックスは、最初の写真の赤いボックスの逆コンパイルされたコードです。画像からわかります:
a+=a は次のことを行います:
Call String.valueOf(a)。 a も文字列であるため、このステップでは新しいオブジェクトは生成されません。
新しい StringBulid (最初のオブジェクトは実際には文字列 a)、このステップでは Stringbuild オブジェクトが生成されます。
.append (追加された文字列)
.toString()、このステップは Stringbuild の toString メソッドを呼び出します。
Stringbuild の toString() ソース コードをもう一度見てみましょう
リーリーおっと!別の String オブジェクトが作成されるのはなぜですか?
a+=a の分析はここで完了しているため、ループ内のすべての文字列追加操作により、実際には少なくとも 1 つの StringBuild オブジェクトと 1 つの String オブジェクトが作成されます。
String は不変オブジェクトであるため、String 型を変更するたびに、実際には新しい String オブジェクトを生成し、新しい String オブジェクトへのポインタを指すのと同じことになるため、頻繁に変更される文字列は使用しないことをお勧めします。オブジェクトが生成されるたびに、特にメモリ内に参照されていないオブジェクトが多すぎると、JVM の GC が動作し始め、速度が大幅に低下するため、String を使用します。 。
頻繁に変更される変数には StringBuffer を使用する必要があります~
... jdk1.8 以降のみ、文字列の複数の連結に StringBuild を使用できます。 。旧バージョンはこうじゃない! ~~
前回記事を読んだのですが、何か間違っているのかわかりません。
1.8 より前では、String を複数回変更する必要がある場合は、StringBuffer または StringBuilder を使用する必要があります。
1.8 では糖衣構文が有効になり、この領域が変更されたため、明示的に StringBuilder を呼び出さなくても高い効率を享受できるようになりました。
文字列の場合は、定数プールに共有オブジェクトのみを作成します。
リーリーここで作成されたオブジェクトはすべて役に立たないオブジェクトではないでしょうか?最終結果に加えて、GC のリサイクルにも時間がかかります。
string は char[] の最終的な変更であるため、毎回新しいオブジェクトを作成する必要があります
StringBuilder が非常に効率的である理由は、通常は演算の追加によって、容量がいっぱいになった場合にのみ配列が動的に拡張されるためです。要約すると、stringbuilder はオブジェクトの生成を減らし、毎回新しいオブジェクトを生成する必要がありません。専門家にアドバイスを求めてください。 ~! ~! ~