2013-05-08 4 views
12

Java文字列がどのように不変であるかを正確に理解しようとしています。私はこれがおそらく簡単なコンセプトになるはずですが、いくつかのオンラインWebページを読んだ後、私はまだそれほど理解していません。Java文字列の仕組み

Java文字列が「不変」であることを理解できません。

Jacob Perkins 
Jacob Perkins! 

は、なぜ、この出来事文字列は不変であるために仮定されている場合:

public static void main(String[] args) { 

    String name = "Jacob Perkins"; 

    System.out.println(name); 

    name = name + "!"; 

    System.out.println(name); 

} 

私の出力は次のようである:私は現在、次のコードを持っていますか?文字列に値を再割り当てできるのはなぜですか?

+0

'String' * variables *は不変ではありません(変数が異なるため!)新しい文字列を作成し、その参照を変数' name'に割り当てました。 – dlev

+0

私はまだ理解していません。 Java文字列で「不変」という用語が表示されるのはなぜですか? – user2301187

+0

@ user2301187:2つの変数が同じ文字列オブジェクトを指すことができます。文字列が変更可能な場合、ある変数の文字列への変更は、他の変数の参照を介して見ることができます。それらがそうでないので、すべての変数は、それが指している文字列が「見ていない間は変更できません」ことを知っています。これは、変更可能な文字列が恐ろしくなり、複雑さが増すためです。変更されないコピーが必要な場合はいつでも文字列のコピーを作成することを忘れてはならないでしょう。 – Patashu

答えて

34

画像があなたのためにこれを説明してみましょう:左側

String example

、あなたは実際に参照ある変数を、持っています。

  1. String name = "Jacob Perkins;"文字列 "Jacob Perkins"が作成され、nameがそれを指します。
  2. name = name + "!";新しい文字列 "Jakob Perkins!"参照が新しい文字列を指すようになりました。しかし、Stringは不変なので、古いものは変更されません。
+4

+1のビジュアル:) – renz

+2

+1の画像! – MadProgrammer

+0

よろしくお願いいたします。私は視覚が助けたと思う。 – user2301187

1

Stringオブジェクトは、変数参照のみが変更されます。

"Jacob Perkins"オブジェクトがまだ存在し、新しいオブジェクト "Jacob Perkins!"作成されます。

名前変数は新しいオブジェクトを指します。

0

実際には、3つのStringオブジェクトが作成されています。 "Jacob Perkins"、 "!"と "Jacob Perkins!" 「Jacob Perkins」のインスタンスを実際に変更していない。名前変数の参照を「Jacob Perkins」インスタンスから「Jacob Perkins!」に変更しました。

+0

「名前変数の参照を変更する」という意味を理解できません。 – user2301187

+0

最初のprintln()では、変数nameが "Jacob Perkins" Stringオブジェクトを指しています。そのオブジェクトは、文字列が不変なので、実際には変更されませんでした。代わりに、2つの新しいStringオブジェクトが作成されます。と "Jacob Perkins!"名前変数は「Jacob Perkins!」を指しています。 実際には3つのStringオブジェクトが作成されましたが、いずれもミュートされていません。 – renz

0
String name = "Jacob Perkins"; 

String name2 = name + "!"; 
name.substring(5); // or wather syntax is 

ものは

5

に文字列自体を変数名を変更しないでください、一度作成され、変更することはできません。どのようなあなたのコードサンプルが行うこと、と感嘆符の前の内容から構築された新しい文字列とで文字列を置換にあります。

コンパイルされたコードを調べる(またはデバッガを使用して手順を実行する)場合は、次のように入力します。 name + "!"の式がStringBuilderオブジェクトの作成とそのオブジェクトのいくつかの操作にコンパイルされていることがわかります。 、文字列ある

は不変ですが、変数名ではありません。その値は、異なる文字列を指すように変更されます。文字列自体は決して変更されません。

0

Javaには参照があり、値があります。

あなたは

String foo = "John Smith";

foo参照を保持し、変数であると言います。参照は、 "John Smith"を含むオブジェクトまたは値を指します。

変数によって保持される参照は変更可能です。私はこれを行うことができます。

foo = "Jack Smith";

そして、私は参照を変異させてきました。しかし、私はこのようなコードを書く場合:

String foo = "John Smith"; 
String bar = foo; //bar's reference is a copy of foo's reference - the same value 
foo = "Jack Smith"; 
System.out.println(bar); //prints John Smith 

私たちはfooを変更したにもかかわらず、バーは変更されていないことがわかります。どうして?単に、foo = "Jack Smith";と書いたとき、fooは新しいStringを指していました。 Javaではメソッドがmutateでなく、文字列を変更することはできません。fooを経由して文字列を変更しませんでした。代わりに新しいStringが返され、変数は新しい不変のStringを指すようにされます。このようにして、オブジェクトの文字列変数 'points'は、その変数を通して決して変更することはできません。これは、それが保証するJava言語の重要な特性です。

1

おそらくこれは理解するのに役立ちます。

たとえば、Point(java.awt.Point)クラスがあるとします。 あなたが1つのインスタンスpを持っているとしましょう:

Point p = new Point(0,0); 

次にあなたが同じオブジェクトpを参照する新しい変数yを作成します:あなたは、pの値を変更した場合、あなたはまた、Yを変更

Point y = p; 

。 Pointクラスは変更可能です。

p.setLocation(1,1); 

これは、y参照を位置1,1とする。

Stringクラスを使用すると、それは起こりません。

String a = "123"; 
String b = a; 

= a + "4"にすると、 aの新しい値は "1234"になりますが、bは "123"です。

参照していたオブジェクトは変更されませんでしたが、今は別のオブジェクトを参照しているということだけです。