Stringオブジェクトが作成されると、それを変更することはできませんが、それに対して何らかの操作を行うと、JVMは新しいオブジェクトを作成します。ここで新しいオブジェクトを作成することにより、JVMはより多くのメモリを消費します。それなら私はそれがメモリの問題を引き起こすと思います。
9 に答える
あなたは正しいです。毎回影響がない場合でも、この問題に注意することは間違いなく価値があります。
あなたが言うように、文字列は作成後に変更することはできません-それらは不変であり、それらを変更するための多くの方法を公開していません。
ただし、split()などの操作では、バックグラウンドで追加の文字列オブジェクトが生成されます。これらの文字列への参照を保持している場合、これらの各文字列にはメモリオーバーヘッド があります。
他のポスターが指摘しているように、オブジェクトは小さく、ガベージコレクションは通常、スコープから外れた後に古いオブジェクトをクリーンアップするため、通常、これについて心配する必要はありません。
ただし、特定のことを行っていて、大量の文字列参照を保持している場合は、これが問題になる可能性があります。
リンク先のページにある警告に注意しながら、ユースケースに応じて 文字列のインターンを確認してください。
注意すべき2つのこと:
1)ハードコードされた文字列リテラルはJavaによって自動的にインターンされ、この影響を軽減します。
2)+演算子は、この点でより効率的です。パフォーマンスとメモリの利点を提供するために、その下で文字列ビルダーを使用します。
いいえ、そうではありません。Stringインスタンスへの強力なリンクを保持していない場合、それらは最終的にガベージコレクターによって収集されます。
例えば:
while (true) {
new String("that is a string");
}
このスニペットでは、新しいオブジェクトインスタンスを継続的に作成しますが、作成されたインスタンスがガベージになるため、OutOfMemoryExceptionが発生することはありません(明らかに強力なリンクはありません)。
新しいオブジェクトのためにより多くのメモリを消費します、そうです。しかし、ガベージコレクターはアクセスできないすべてのメモリを即座に再利用するため、その事実自体は問題を引き起こしません。もちろん、新しく作成された文字列へのリンクを作成することで問題に変えることができますが、それはJVMではなくプログラムの問題になります。
あなたが知らなければならない最大のメモリの問題は、巨大な文字列の小さな部分文字列を取ることです。そのサブ文字列は元の文字列のchar配列を共有し、元の文字列がgcされた場合でも、巨大なchar配列はサブ文字列によって参照されます。回避策はを使用することnew String(hugeString.substring(i))
です。
未使用のオブジェクトはGCによって収集されます。
不変性はJavaで多くの利点を得ました。
Javaでは、可能な限り多くの不変性を実現することをお勧めします。
これらは、コレクションフレームワークでも安全に使用できます。
発生する問題は、ごみが発生するという事実です。この問題は、ガベージコレクターを呼び出して、そのガベージによって使用されているメモリを解放することにより、仮想マシンによって解決されます。
古いオブジェクトが使用されなくなるとすぐに、ガベージコレクターによって削除できます。(これは、メモリの問題が発生するずっと前に行われます)。
データのコピーを防ぎたい場合は、StringBuilderを使用してください。
私の知る限り、StringBuilder(またはスレッドセーフの場合はStringBuffer)は、Stringを管理し、それらを可変にするのに役立ちます。
巨大な文字列内の一部の文字を操作しても、メモリ内の多くのバイトが「食べられない」。
また、concateの場合はより強力/高速です。
文字列インスタンスは不変であるため、jvmで再利用できます。Stringクラスは、メモリの問題を回避するために使用されるFlyweightDesignPatternで実装されます。