web-dev-qa-db-ja.com

文字列リテラルはスタックに保存されていますか?新しい文字列はスタックに保存されていますか?

可能性のある複製:
文字列オブジェクトと文字列リテラルの違い

2つのステートメントがあるとします。

String one = "abc";
String two = new String("abc");

スタックメモリとヒープに格納されているのはどれですか?

これら両方の違いは何ですか?

いくつのオブジェクトが作成され、メモリ内の参照はどのくらいですか?

ベストプラクティスは何ですか?

30
Some Java Guy

すべてのオブジェクトはヒープに格納されます(属性を含む)。1

ローカル変数(引数を含む)には常にプリミティブ値または参照が含まれ、スタックに保存されます。1

したがって、2行の場合:

String one = "abc";
String two = new String("abc");

ヒープ上に2つのオブジェクトがあります("abc")スタック上の2つの参照(各オブジェクトに1つ)(oneおよびtwoはローカル変数であることが前提)。

(実際、正確には、文字列リテラルなどのインターンされた文字列に関しては、いわゆる文字列プールに格納されます。)

オブジェクトがいくつ作成され、メモリ内の参照はどのくらいですか?

文字列はJava言語では特別なものです。

1つは保証ですが、newを使用するたびにnew参照が得られます。これは、twonotoneと同じオブジェクトを参照することを意味します。つまり、これらの2行のコードの後に​​ヒープ上に2つのオブジェクトがあります。


1)正式に言えば、Java Language Specificationは、値をメモリに格納する方法または場所を指定しません。これ(またはそのバリエーション)は、実際に通常行われる方法です。

23
aioobe

1つ目はString Literalとして呼び出され、プログラムのコンパイルの時点で作成され、2つ目はstring objectで作成されます実行時。

2番目のケースでnewキーワードを使用したため、ヒープに割り当てられます。

最初のケースでは、オブジェクトはinterningと呼ばれるメカニズムで作成されます。同じ文字シーケンスを表す別の文字列リテラルを作成しようとすると、新しいオブジェクトコンパイラを作成する代わりに、string poolに作成および保存された以前の文字列を参照します

7
Chandra Sekhar

プリミティブ型(int、long、...)のインスタンスのみがスタックに保存されます。参照型のすべてのインスタンス(StringIntegerLongYourTypeHere、...)はヒープに保存されます。

[〜#〜] update [〜#〜]コメントで指摘されているように、参照型のインスタンス(つまり、非プリミティブ型-Objectとその子孫への参照) )スタックに保存できます。これらはローカル変数です。

これは「ベストプラクティス」ではなく、JVMの動作方法であり、変更することはできません。

4
Victor Sorokin

あなたの場合、2つのStringオブジェクトが作成されます。通常、すべてのオブジェクトはヒープ上に作成されます。ただし、文字列1は文字列リテラルであるため、これは文字列プール(PermGen内)に格納されます。 intern() メソッドを使用して、文字列を文字列プールに追加し、その参照を取得することもできます。

投稿した宣言がメソッド内にある場合、referencesはスタックに格納されますが、オブジェクト自体には格納されません。

に関しては、ベストプラクティスはString one = "abc"になると思います。

これには2つの理由があります。

  1. コードはきれいです
  2. インターンされた文字列は、等しいよりも速い==と比較できます。ただし、非リテラル文字列を比較する前にintern()する必要があります。

編集:あなたはこのリンクをチェックアウトすることに興味があるかもしれません: エスケープ分析Java SE 7 。オブジェクト割り当てに影響するいくつかのHotSpot関連の最適化を提示します。

3
Filip