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

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

ただいまの
回答率

90.48%

  • Java

    14082questions

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

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

解決済

回答 5

投稿

  • 評価
  • クリップ 0
  • VIEW 913

Anoaji

score 40

前提・実現したいこと

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);

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+4

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

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

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/17 18:18

    リンクの参照に関しては、理解しており、同じ場所をさしていて、その場所の中身が変更したのに、なぜ値が変わるのか?が疑問でした。

    しかしながら皆様のおかげで理解できました。要は別の文字の場合は、内部でnew StringBuilderをしているから、別のインスタンスが作られ、新たな参照場所を指すようになるってことですね。皆様ありがとうございました

    キャンセル

  • 2016/02/17 18:22

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

    キャンセル

  • 2016/02/17 18:26

    この場合はStringBuilderは関係ないです。

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

    キャンセル

  • 2016/02/25 13:01

    返信いただいてたんですね。ありがとうございます。
    String a = "hoge"; //111を指している
    String b = a;   //aもbも111を指している
    String b = "foo";   

    この場合、111の中身(値)がfooになったという認識でいました。
    それぞれ全く別のもので、newしていると考えたら、納得できました。
    ありがとうございました。

    キャンセル

+2

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

public class MyClass {
    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);
        System.out.print("\n");

        StrHolder sh1 = new StrHolder();
        StrHolder sh2 = sh1;
        sh1.setStr("UPDATED_X");
        System.out.print(sh1.getStr());
        System.out.print(", ");
        System.out.print(sh2.getStr());

        System.out.print("\n");
        System.out.println(s1 == s2);
        System.out.println(sh1 == sh2);
    }
}
class StrHolder {
    private String str = "ORIGINAL_X";

    public void setStr(String s) {
        this.str = s;
    }
    public String getStr() {
        return this.str;
    }
}


実行結果

UPDATED, ORIGINAL
UPDATED_X, UPDATED_X
false
true

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

-1

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

public static void main(String[] args) throws Exception {
    List<String> list1 = new ArrayList<>();
    list1.add("aaa");

    List<String> list2 = list1;
    list1.set(0, "bbb");

    System.out.println(list2.get(0)); // bbb と表示
}

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/17 18:22

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

    キャンセル

  • 2016/02/18 01:50

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

    キャンセル

  • 2016/02/25 13:01

    返信いただいてたんですね。ありがとうございます。
    String a = "hoge"; //111を指している
    String b = a;   //aもbも111を指している
    String b = "foo";   

    この場合、111の中身(値)がfooになったという認識でいました。
    それぞれ全く別のもので、newしていると考えたら、納得できました。
    ありがとうございました。

    キャンセル

  • 2017/02/17 13:07

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

    キャンセル

  • 2017/02/17 15:04

    上記ソースでは他の参照型と同様のことが起きるのに、なぜ質問者さんのソースでは起きないのか?
    というところが言いたかったのですが、確かにちょっと説明不足ですね。。。

    "a" == "a" が true になるわりに、new String("a") == new String("a") は false になって、equals使わないとダメなとことか。
    では、new String("a") を引数に渡すと参照が渡るのかと言うとコピーが渡ったりと、
    何かと不可解な動きをしますよね。

    文字列リテラルはキャッシュされるので、"a" は単純に new String("a") のシンタックスシュガーではないわけで、何だかややこしいなぁと思います。
    これもJavaが純粋オブジェクト指向ではないと言われる所以なのだと思うのですが、どうでしょうか?

    キャンセル

  • 2017/02/17 15:19

    >new String("a") を引数に渡すと参照が渡るのかと言うとコピーが渡ったり
    ん~厳密には参照が渡っているかもしれませんね。
    private void foo(String str) {
    str = "UPDATE";
    }
    として呼び出し元に影響がないのは、"UPDATE"で新たなインスタンスができて、
    参照値を代入してるから影響がないのか。
    引数のListに、list.add("UPDATE") すれば呼び出し元に影響があるけど、list = new ArrayList(); は
    参照値のコピーだから影響がないのと同じように。

    では、このメソッド内で String が内部で持つ char配列をリフレクションで無理矢理変更すれば、呼び出し元に影響が出てくるのか。。。
    いずれにしても曖昧な知識で混乱させる事を書いてしまいましたね。。。失礼しました。

    キャンセル

  • 2017/02/17 23:17

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

    キャンセル

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

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    Javaで文字コードの変換をしたい

    前提・実現したいこと 今Javaで文字コードの扱いについて勉強しています。 発生している問題・エラーメッセージ 一度UTF-8からShift_JISに変換したあともう一度

  • 解決済

    System.out.printからSystem.out.writeへの書き換え

    単純な足し算プログラムの書き換えができません。 System.out.printではなく、System.out.writeを使用するプログラムに書き換えたいのですが、 うま

  • 受付中

    オブ

    下記うお願いします。本質問に関係ない処理が記載されていますが気にしないでください。よ         Donut d1 = new Dc2);          Syste

  • 解決済

    入力した値を表示させない方法

    初めまして。現在JAVAを学んでいる初心者です。 現在、配列に格納している値を表示させるプログラムを作っています。 ユーザーから入力があった場合、次に配列の値を表示させるとき、

  • 解決済

    Javaでの文字コード値取得について

    public static void main(String args[]) { char a = 'あ'; System.out.println(

  • 解決済

    Javaでの文字コード値取得について

    Javaでutf-8のコード値からunicodeに変換するにはどうすればいいでしょうか? public static void main(String[] args) {

  • 解決済

    偶数だけ出したい

    public class Main { public static void main(String[] args) throws Exception { for (int

同じタグがついた質問を見る

  • Java

    14082questions

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