2011-04-29 14 views
16

次のJavaコードセグメントは、AP Computer Science練習試験のものです。Java文字列変数の設定 - 参照または値ですか?

String s1 = "ab"; 
String s2 = s1; 
s1 = s1 + "c"; 
System.out.println(s1 + " " + s2); 

このコードの出力は、BlueJの「abc ab」です。しかし、可能な回答選択肢の1つは "abc abc"です。その答えは、JavaがString型の参照をプリミティブ型(値による)やObject(参照による)のように設定するかどうかによって決まります。

int s1 = 1; 
int s2 = s1; // copies value, not reference 
s1 = 42; 

System.out.println(s1 + " " + s2); // prints "1 42" 

をしかし、我々はバランスを保持する銀行口座のオブジェクトを持っていたと言う:

はこれをさらに説明するために、プリミティブ型で例を見てみましょう。

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter 
BankAccount b2 = b1; // reference to the same object 
b1.setBalance(0); 
System.out.println(b1.getBalance() + " " + s2.getBalance()); // prints "0 0" 

文字列にはどのような場合がありますかわかりません。彼らは技術的にオブジェクトですが、私のコンパイラは、変数を互いに設定するときに、それらをプリミティブ型のように扱うようです。

Javaがプリミティブ型のような文字列変数を渡す場合、答えは "abc ab"です。しかし、Javaが文字列変数を他のオブジェクトへの参照のように扱う場合、答えは "abc abc"になります

あなたはどちらが正解であると思いますか?

+0

文字列のドキュメントを見ましたか?それがクラスかプリミティブかどうかは分かりますか? – DJClayworth

+0

あなたの質問に答えて、[javadoc](http://download.oracle.com/javase/6/docs/api/java/lang/String.html)を読んでみてください。 –

+4

'System.out.println(s1 +" "+ s2); // print "1 42"は真ではありません。それは '' 42 1 "' – whytheq

答えて

27

java文字列は不変です。したがって、再割り当てによって、実際にはStringの値を変更するのではなく、変数が新しいStringのインスタンスを参照します。

String s1 = "ab"; 
String s2 = s1; 
s1 = s1 + "c"; 
System.out.println(s1 + " " + s2); 

2行目、s1 == s2 AND s1.equals(s2)です。 3行目の連結の後、s1は不変の値 "abc"を持つ別のインスタンスを参照するようになり、s1 == s2もs1.equals(s2)もそうではありません。

+1

それはありますが、実際にはOPのより基本的な質問には答えません。 –

+5

もちろんです。それは暗黙のうちに、StringのケースとBankAccountの比較が同じではないことを説明しています。 1つは新しいインスタンスを割り当て、もう1つは既存のインスタンスを単純に変更することです。明快にするために、s1 = s1 + "c"は基本的にb = new StringBuilder(s1); b.append( 'c'); s1 = b.toString(); – Robin

2

java.lang.Stringはオブジェクトでありプリミティブではありません。コードは、最初の例でやった

は次のとおりです。

  1. 「AB」
  2. セットS2同じ基礎オブジェクトに等しいS1などとしてS1を定義
  3. セットS1、新しい文字列に等しいことs1の古い値と "c"の組み合わせです

しかし、参照や値についてのあなたの質問に答えるには参考にしてください。

6

Javaでは、Stringオブジェクトはを参照して割り当てられ、渡されます。;これは他のオブジェクトとまったく同じように動作します。

ただし、Stringです。:新しいオブジェクトを作成せずに既存の文字列の値を変更する操作はありません。たとえば、s1 = s1 + "c"は新しいオブジェクトを作成し、s1に格納されている参照をこの新しいオブジェクトへの参照に置き換えます。

9

Stringがプリミティブのように扱われるかオブジェクトのように扱われるかは関係ありません!

Stringの例では、2つの文字列を連結すると、新しい文字列インスタンスが生成され、次にそれがs1に割り当てられます。変数s2は変更されていない(!)古いStringインスタンスを参照しています。銀行口座のを想定し

は新しい銀行口座のを返すのバランスを設定するためのメソッドを持っていた、あなたの例は次のようになります。

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter 
BankAccount b2 = b1; // reference to the same object 
b1 = b1.createNewAccountWithBalance(0); // create and reference a new object 
System.out.println(b1.getBalance() + " " + b2.getBalance()); // prints "0 500" 
13

あなたの銀行口座のと文字列の違いは、文字列は不変であるということです。 'setValue()'や 'setContent()'のようなものはありません。銀行口座と同等の例は次のようになります。

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter 
BankAccount b2 = b1; // reference to the same object 
b1 = new BankAccount(0); 
System.out.println(b1.getBalance() + " " + s2.getBalance()); // prints "0 500" 

あなたはそれを考えるのであれば、この方法は、(ない実際にコンパイラが何をするかが、機能的に同等の)文字列連結のシナリオは次のとおりです。

String s1 = "ab"; 
String s2 = s1; 
s1 = new String("abc"); 
System.out.println(s1 + " " + s2); //prints "abc ab" 
9

実際、Stringはクラスであり、参照によって割り当てられています。 しかし、混乱何が文です:

String s = "abc"; 

文字列(「int x = 10;」のような)primitveであることを示唆しています。 これは単なるショートカットです。 'String s = "abc";'実際には「Integer x = 10;」はこの仕組みが「ボクシング」と呼ばれる「Integer x = new Integer(10);

としてコンパイルされたと同じように「String s = new String("abc");」 としてコンパイルされます。クラスのInteger 'と原始的「int」、 がありますが、(char[]が近づくallthough)文字列は

Sijeデ・ハーン

0
int s1 = 1; 
int s2 = s1; // copies value, not reference 
s1 = 42; 

System.out.println(s1 + " " + s2); // prints "1 42" 
プリミティブ相当するものがありません。

そして、より多くの混乱があります

"1 42"しかし"42 1"を印刷しないでください。各個別の行を考慮してください。最初のs1は1を割り当て、次にs2はs1を割り当てます(今はJavaが3行目をまだ見ていないと仮定します)。javaは3行目とすぐにcそのjavaがそれまでに知っていたものを印刷するように言われた後、s1は42でs2は1(古いs1)です。

文字列についても同じことが起こります。

String s1 = "ab"; 
String s2 = s1; 
s1 = s1 + "c"; 
System.out.println(s1 + " " + s2);// prints "abc ab". 

フォート文字列それは必ずしもS1変わりないのではなく、今ヒープメモリに新しいStringオブジェクトを指しS1、しかし、古い「AB」オブジェクトは、S2の新しい参照して、まだそこにあります!

0

Javaは、他のオブジェクトへの参照のような文字列変数を扱う場合、アサーションは、答えは "ABC ABC"

が間違っているだろう。 JavaはString変数を他のオブジェクトへの参照と同様に扱います。 Stringsはオブジェクトですが、答えは "abc ab"です。

問題は代入演算子の機能ではありません。代入演算子は、例のすべての場合にStringオブジェクトへの参照を割り当てます。

問題は連結演算子( '+')が行う問題です。新しいStringオブジェクトを作成します。他にも述べたように、Stringオブジェクトは不変なので、これは必要ですが、Stringが不変であるだけでなく、演算子の動作の問題です。連結演算子は、Stringオブジェクトが変更可能であっても新しいObjectを返すことができます。

これに対して、2番目の例では、b1.setBalance(0)は新しいオブジェクトを作成せず、既存のオブジェクトを変更します。

関連する問題