質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

5回答

2009閲覧

String型について(短いコードです)

Anoaji

総合スコア49

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2016/02/17 08:31

###前提・実現したいこと
String(参照型)について理解したい。

###質問
以下のコードをコンパイル・実行すると
【UPDATED, ORIGINAL】となるのですが、
私としては両方UPDATEになるべきだと思っています。理由は以下です。
①s1とs2は同じ場所を参照している
②s1="UPDATE"でs1にある値を変更したから。

私の認識のどこが間違っているんでしょうか。
ご教示お願いします。

###ソースコード

public class Main { public static void main(String[] args) { String s1 = "ORIGINAL"; String s2 = s1; //① s1 = "UPDATED"; //② System.out.print(s1); System.out.print(", "); System.out.print(s2); } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

String s1 = "ORIGINAL";では、"ORIGINAL"の参照値をs1に代入しています。

①では、s1に代入された参照値をs2にコピーして代入しています。

②では、"UPDATE"の参照値をs1に代入しています。
このとき、s2に入っている参照値は"ORIGINAL"の参照値のままです。

(追記)
下記のページにある画像を例にすると、赤い点が参照値の部分です。オブジェクトは文字列などが該当します。

http://homepage3.nifty.com/teranet/JavaPrograming/javaClass7.html

投稿2016/02/17 08:45

編集2016/02/17 08:51
argius

総合スコア9390

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Anoaji

2016/02/17 09:18

リンクの参照に関しては、理解しており、同じ場所をさしていて、その場所の中身が変更したのに、なぜ値が変わるのか?が疑問でした。 しかしながら皆様のおかげで理解できました。要は別の文字の場合は、内部でnew StringBuilderをしているから、別のインスタンスが作られ、新たな参照場所を指すようになるってことですね。皆様ありがとうございました
swordone

2016/02/17 09:22

Stringは不変クラスであり、中身が書き変わることはありませんよ。 単純に別のStringをnewしているだけです。
argius

2016/02/17 09:26

この場合はStringBuilderは関係ないです。 "ORIGINAL"と"UPDATED"のStringクラスのインスタンスは常に1つずつで、String型の変数に入れるのは参照値です。参照値はコピーされるので、①の時点ではs1とs2には同じ"ORIGINAL"を指す参照値が入っています。 ②のときは、s1にもともと入っている"ORIGINAL"の参照値を捨てて、"UPDATED"の参照値を入れています。この操作では、s2に入っている"ORIGINAL"の参照値に影響はありません。
Anoaji

2016/02/25 04:01

返信いただいてたんですね。ありがとうございます。 String a = "hoge"; //111を指している String b = a;   //aもbも111を指している String b = "foo";    この場合、111の中身(値)がfooになったという認識でいました。 それぞれ全く別のもので、newしていると考えたら、納得できました。 ありがとうございました。
guest

0

s1 = "UPDATED"; では ORIGINAL の文字列が UPDATED に変更されるわけではありません。
UPDATED の文字列が生成され、その参照が s1 に入ります。
s2 は ORIGINAL の文字列の参照のままです。

投稿2016/02/17 08:43

yoshi777

総合スコア674

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

イメージされているのは、以下のようなことですよね?

java

1public static void main(String[] args) throws Exception { 2 List<String> list1 = new ArrayList<>(); 3 list1.add("aaa"); 4 5 List<String> list2 = list1; 6 list1.set(0, "bbb"); 7 8 System.out.println(list2.get(0)); // bbb と表示 9}

Stringはかなりの特別扱いで特殊なんですよ。
分かりづらいですよね。。。

投稿2016/02/17 09:17

root_jp

総合スコア4666

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Anoaji

2016/02/17 09:22

そうです。。Stringは通常の参照型と思ったら手ごわいですね。
swordone

2016/02/17 16:50

この辺の仕組みはStringであろうと他の参照型であろうと全く同じだと思うのですが…
Anoaji

2016/02/25 04:01

返信いただいてたんですね。ありがとうございます。 String a = "hoge"; //111を指している String b = a;   //aもbも111を指している String b = "foo";    この場合、111の中身(値)がfooになったという認識でいました。 それぞれ全く別のもので、newしていると考えたら、納得できました。 ありがとうございました。
yuba

2017/02/17 04:07

swordoneさんご指摘の通りでStringは少しも特別扱いされてはいません。訂正が必要です。
root_jp

2017/02/17 06:04

上記ソースでは他の参照型と同様のことが起きるのに、なぜ質問者さんのソースでは起きないのか? というところが言いたかったのですが、確かにちょっと説明不足ですね。。。 "a" == "a" が true になるわりに、new String("a") == new String("a") は false になって、equals使わないとダメなとことか。 では、new String("a") を引数に渡すと参照が渡るのかと言うとコピーが渡ったりと、 何かと不可解な動きをしますよね。 文字列リテラルはキャッシュされるので、"a" は単純に new String("a") のシンタックスシュガーではないわけで、何だかややこしいなぁと思います。 これもJavaが純粋オブジェクト指向ではないと言われる所以なのだと思うのですが、どうでしょうか?
root_jp

2017/02/17 06:19

>new String("a") を引数に渡すと参照が渡るのかと言うとコピーが渡ったり ん~厳密には参照が渡っているかもしれませんね。 private void foo(String str) { str = "UPDATE"; } として呼び出し元に影響がないのは、"UPDATE"で新たなインスタンスができて、 参照値を代入してるから影響がないのか。 引数のListに、list.add("UPDATE") すれば呼び出し元に影響があるけど、list = new ArrayList(); は 参照値のコピーだから影響がないのと同じように。 では、このメソッド内で String が内部で持つ char配列をリフレクションで無理矢理変更すれば、呼び出し元に影響が出てくるのか。。。 いずれにしても曖昧な知識で混乱させる事を書いてしまいましたね。。。失礼しました。
swordone

2017/02/17 14:17

ちょっとStringを始め参照型についてきちんと勉強し直したほうがいいですよ。
guest

0

String については他の方の回答の通りです。
ここで、次のコードと、実行結果をみてください。
String をメンバーのもつクラスを定義し、そのインスタンスについて、同様のことを行ってみています。

java

1public class MyClass { 2 public static void main(String[] args) { 3 String s1 = "ORIGINAL"; 4 String s2 = s1; // ① 5 s1 = "UPDATED"; // ② 6 System.out.print(s1); 7 System.out.print(", "); 8 System.out.print(s2); 9 System.out.print("\n"); 10 11 StrHolder sh1 = new StrHolder(); 12 StrHolder sh2 = sh1; 13 sh1.setStr("UPDATED_X"); 14 System.out.print(sh1.getStr()); 15 System.out.print(", "); 16 System.out.print(sh2.getStr()); 17 18 System.out.print("\n"); 19 System.out.println(s1 == s2); 20 System.out.println(sh1 == sh2); 21 } 22} 23class StrHolder { 24 private String str = "ORIGINAL_X"; 25 26 public void setStr(String s) { 27 this.str = s; 28 } 29 public String getStr() { 30 return this.str; 31 } 32}

実行結果

UPDATED, ORIGINAL UPDATED_X, UPDATED_X false true

このような結果になることが理解できますか?

投稿2016/02/17 13:02

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

s2への代入は①で終わっています。(s2の値は確定しています)
printの前で再度代入しなければs2は変更されません。

投稿2016/02/17 08:51

makoto-n

総合スコア436

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問