2013-08-07 8 views
10

プログラム内の以下のステートメントでは、ヒープメモリと文字列定数プールにいくつのオブジェクトが作成されますか?Javaおよびメモリ管理のオブジェクトライフサイクル?

私はオブジェクトの作成を明確にする必要があります。私が読んだ多くの情報源は詳しく述べていない。オブジェクトが破壊されると混乱します。

String a="MAM"+"BCD"+"EFG"+"GFE"; 

作成するオブジェクトの数はいくつですか?

私は、オブジェクト、メソッド、クラスのライフサイクルと、動的に変更および変更されたときにJVMがそれらをどのように処理するかについて、良いマテリアルを探しています。

+0

あなたはどう思いますか? –

+0

誰かが 'javah'を実行するだけです。私はそれが1つだけの定数を表示すると思います。 – Rekin

+0

私だけがこのディスカッションの中で1人だけ多くの友人が私を混乱させた [link](https://www.facebook.com/groups/java.for.developers/10151748401034501/?notif_t=group_comment_reply) – saikiran

答えて

3

既存のオブジェクトが既に使用されている場合を除いて、1つのオブジェクトが作成され、定数プールに配置されます。コンパイラは、JLS 3.10.5および15.28で指定されているように、文字列定数を連結します。リテラル

長い文字列は、常に短い小片に分割し、文字列連結演算子を使用して、(おそらく括弧)式のように書くことができる+

http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5

6

オブジェクトは1つだけ作成されます。

string s1 = "java"; 
string s2 = "ja" + "va"; 
s.o.p(s1==s2); 

このステートメントはtrueになります。

String s1="java"; 
string s2 = "ja"; 
String s3 = s2 +"va"; 
s.o.p(s1==s3); 

このステートメントはfalseになります。

したがって、「+」演算子はnew()を使用して非定数プール内に新しい文字列オブジェクトを生成します。 あなたが聞いた質問には永久的なものもありません。つまり、オブジェクトは1つしか作成されません。

20

"MAM"+"BCD"+"EFG"+"GFE"は、コンパイル時ですそれは"MAMBCDEFGGFE"文字列リテラルにコンパイルされます。 JVMは、上記のコードを含むクラスをロードするときに、このリテラルからStringのインスタンスを作成し、Stringを文字列プールに配置します。したがってString a = "MAM"+"BCD"+"EFG"+"GFE";が任意のオブジェクトを作成しない、参照JLS 15.18.1. String Concatenation Operator +

Stringオブジェクトを新規に作成する(§12.5)式は、コンパイル時定数式(15.28)である場合を除き。

単にプール内のオブジェクトStringへの参照をローカル変数aに割り当てます。

+0

私は今コンセプトを得ました。@Evgeniy – saikiran

2

String a"MAMBCDEFGGFE"にコンパイルされるため、1つのオブジェクトのみが作成されます。

0

例内に単一のヒープオブジェクトを示す回答が正しいとします。ただし、次のコードを検討してください。

public class Tester 
{ 
    public String a="MAM"; 
    public String b ="BCD"; 
    public String c = "EFG"; 
    public String d ="GFE"; 

    public Tester() 
    { 
     String abcd = a + b + c + d; 
    } 
} 

この例では、7つの文字列が作成されています。 a、b、c、dは単一の定数にコンパイルされません - メンバーです。 1つの文字列が各+演算子ごとに作成されます。つまり、意味的には+は連結ですが、論理的には新しい文字列をメモリに作成しています。最初の2つの演算子文字列はすぐに破棄され、ガベージコレクションの対象になりますが、メモリチャーンは引き続き発生します。

技術的には8番目のオブジェクトにあります。 Testerのインスタンス。

編集:これは

+3

javacコンパイラには最適化があります。それぞれの '+'が新しい文字列を生成するわけではありません。内部で 'StringBuilder'が生成された後、' a'、 'b'、' c'、 'c'が追加され、一つの' String'が作成されます。この最適化は10年以上にわたって行われてきました。したがって、計算は5つの 'String'と5つの' char [] '、1つの' StringBuilder'と少なくとも1つの関連する 'char []'です - 最終的には動的サイズ変更によるものです。 –

+0

私は訂正しました! +1 – Gusdor

+0

あなたは最初に+ bを追加して、+ bを1つの文字列として考え、cに追加することを意味しますか?私はあなたを取得していない – saikiran

3

ほとんどの答えはa)の完全な表現が1つのコンパイル時定数であることを集中するようだと、b)ライン自体は建設しないことをコメントでナンセンスであることが証明されました新しいオブジェクトですが、という1つのオブジェクトへの参照のみです。オブジェクトです。

これまで誰も言及していませんが、String自体には、char[](定数プールにもあります)への参照が含まれています。

要約:定数プールには2つのオブジェクトがあります(Stringおよびchar[])。この行は、オブジェクトを作成も破棄もしません。

そしてについて:

オブジェクトが破棄されますとき、私は混乱しています。

定数プールの内容は、クラス自体がアンロードされる場合にのみ破棄されるため、オブジェクトは破棄されません。ほとんどの場合、参照aは最終的に範囲外になると言えます。

関連する問題