Javaの参照型変数についての質問

このQ&Aのポイント
  • Javaの参照型変数に関する質問です。正解の選択肢はA、D、F、Gですが、Eの選択肢がfalseになる理由が分からないです。
  • s3も文字列Helloのオブジェクトを生成しているので、s3 == "Hello"もtrueだと思います。アドバイスをお願いします。
  • 質問文章はJavaの参照型変数についての問題で、正解の選択肢はA、D、F、Gです。しかし、Eの選択肢がfalseになる理由が分かりません。アドバイスをお願いします。
回答を見る
  • ベストアンサー

Javaの参照型変数についての質問です。

SUN教科書Javaアソシエイツ P209 問5-7より 次のプログラムの空欄(1)に入れて実行すると、出力結果がtrueになる コードはどれですか。4つ選択して下さい。 class Sample{ public static void main(String[] args){ String s1 = "Hello"; String s2 = "Hello"; String s3 = new String("Hello"); System.out.println(【  (1)  】) } } A. s1 == s2 B. s1 == s3 C. s2 == s3 D. s1 == "Hello" E. s3 == "Hello" F. s1.equals(s3) G. s2.equals(s3) 以上が問題です。正解の選択肢はA,D,F,Gです。 正解については理解出来ています。しかし、Eの選択肢もtrueに なると思うのですがどうしてfalseなのでしょうか。 s1とs2が文字列Helloを参照しているのは分かります。 しかし、String s3 = new String("Hello");で、 s3も文字列Helloのオブジェクトを生成しているのですから、 s3もHelloを参照していることになり、s3 == "Hello"も trueになると思うのですが…。 アドバイス、よろしくお願い致します。

  • Java
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • jjon-com
  • ベストアンサー率61% (1599/2592)
回答No.3

JavaにおけるString型変数は「参照」を格納する変数であり, 参照とは何か?を敢えて言い切ってみるとそれはアドレス・番地・ポインタです。 質問文のコードを実行した際,JavaVM上でリテラル"Hello"が確保された先頭番地が例えば40000番地であったと仮定する。 ▼String s1 = "Hello"; においてs1に代入されるのはその番地の値40000です。 質問文のコードには同一リテラルの"Hello"が3回登場しますが,   String s1 = "Hello";   String s2 = "Hello";   String s3 = new String("Hello"); 同一リテラルである場合は3つ別々に確保するのではなく1つだけ確保してそれを共用しようとするのがJavaの特徴だというのはANo.2で解説されているとおり。 よって, ▼String s2 = "Hello"; においてs2に代入されるのも40000です。 ▼String s3 = new String("Hello"); だけは違って,先頭番地40000を引数として与えて,別の場所に文字列を新たにnewで確保している。よって元の40000番地とは別の場所に文字列が確保されます。s3に代入されるのは40000ではない値(非40000)です。 結論として,equalsによって「参照が指し示す先の内容を比較」するのではなく,==によって「参照値自体を比較」するのであればこうなります。 A. s1 == s2(40000 == 40000) B. s1 == s3(40000 == 非40000) C. s2 == s3(40000 == 非40000) D. s1 == "Hello"(40000 == 40000) E. s3 == "Hello"(非40000 == 40000)

taro_11
質問者

お礼

参照型変数・リテラル・番地などの具体的な例を用いての解説はすごく分り易かったです。 本当にありがとうございました。

その他の回答 (2)

  • root139
  • ベストアンサー率60% (488/809)
回答No.2

String(String) コンストラクタでは、引数と同じ文字シーケンスを表す新しいオブジェクト(インスタンス)が生成されます。 http://java.sun.com/javase/ja/6/docs/ja/api/java/lang/String.html#String%28java.lang.String%29 つまり、new String("Hello") では、「Hello」を表すが引数の "Hello" とは別のオブジェクトが生成されます。また、 == で判定されるのは同じインスタンスか否かです。 したがって、new String("Hello") == "Hello" は false となります。 ちなみに A と D が true になる理由は、Javaの言語仕様に「文字列リテラルは常にクラス String の同じインスタンスを参照する」という決まりがあるからです。このことから "Hello" はどこに現れても同じインスタンスとなります。 個人的には、リテラルのインスタンスを指している事が分かっているString変数同士の比較であっても、必ず equals を使う方が良いと思っていますので、実際のコードでString同士を == で比較することはまず無いです。 (インスタンスの同一性が問題になる場合を除く)

taro_11
質問者

お礼

返信ありがとうございました。 おかげで理解が深まりました。

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.1

> s3も文字列Helloのオブジェクトを生成しているのですから、 > s3もHelloを参照していることになり ここがおかしい。 参照型の場合、==は参照している所が同一かどうかを確認し、内容が一致しているかどうかは確認しません(内容一致の確認はequals()の仕事です)。 このプログラムの場合、s1とs2はシステムがリテラルとして用意したHelloを参照し、s3はリテラルのHelloを元にプログラム内で新たに生成したHelloを参照しています。内容が同じでもその存在している場所が異なるため、==では別物と認識されます。

taro_11
質問者

お礼

とても親切で詳細な解説をありがとうございました。

関連するQ&A

  • JAVAアソシエイツの問題

    「SUN教科書 JAVAアソシエイツ P209 問5-7」からの問題についてです。 次のプログラムの空欄(1)に入れて実行すると、出力結果がtrueになる コードはどれですか。4つ選択してください。 class Sample{ public static void main(String[] args){ String s1 = "Hello"; String s2 = "Hello"; String s3 = new String("Hello"); System.out.println( 【(1)】 ); } } A. s1 == s2 B. s1 == s3 C. s2 == s3 D. s1 == "Hello" E. s3 == "Hello" F. s1.equals(s3) G. s2.equals(s3) 正解はADFGです。AFGに関しては理解出来るのですが、 どうして選択肢Dがtrueなのに選択肢Eはfalseになるのでしょうか。 よろしくお願い致します。  

    • ベストアンサー
    • Java
  • Javaの参照型変数の比較についての質問です。

    SUN教科書Javaアソシエイツ P209 問5-8より 出力結果を問う問題です。 class A{String s = ”ABC”;} class Sample{ public static void main(String[] args){ A a1 = new A(); A a2 = new A(); if(a1 == a2){ System.out.println("a1 == a2"); } if(a1.s == a2.s){ System.out.println("a1.s == a2.s"); } if(a1.equals(a2)){ System.println("a1 equals a2"); } if((a1.s).equals(a2.s)){ System.out.println("a1.s equals a2.s"); } } } 【解答】 a1.s == a2.s a1.s equals a2.s 「a1.s」と「a2.s」の記述、つまり表記が意味している内容が良く分かりません。 a1とa2が別のオブジェクトであることは理解出来ています。 ですから、(a1 == a2)と(a1.equals(a2))がfalseとなるのも分かります。 ですが、「a1.s」の「.s」とは何なのでしょうか。 解説には「a1.sとa2.sはAクラスのオブジェクトが保持する同一のStringオブジェクトを 参照しています。」とあります。Aクラスを生成した時にその中にString型クラスsが 作れているということでしょうか。 アドバイスをよろしくお願い致します。

    • ベストアンサー
    • Java
  • 参照型変数の比較について

    1,2のソースについての質問となります。 ご教授の程お願い致します。 ◇◆1◆◇ class Sample{ public static void main(String args[]){ String s1 = "Hello"; String s2 = "Hello"; String s3 = new String("Hello"); System.out.println(s1 == "Hello"); //(1) } } ◇◆2◆◇ class Sample{ public static void main(String args[]){ String s1 = "Hello!Java"; String s2 = s1; s1 = s1.substring(6); //(2) System.out.println(s1); //(3) System.out.println(s2); //(4) } } ○1の質問 (1)の部分になりますが、 「s1 == "Hello"」の結果がtrueとなる理由が理解しずらいです。 「==」演算子では、「同じオブジェクトを参照しているか」を 比較するものであって、この場合「オブジェクトと文字列」の比較を しているので、falseになると思われます。 仮に、Helloがオブジェクトとして捉えられている場合であっても 「String s3 = new String("Hello");」で作成されたオブジェクトを 参照しているものとなるので、s1と比較をしてもfalseになると 思われます。 ○2の質問 このソースを実行後、 Java Hello!Java と、出力される理由についての質問となります。 (2)で「Java」の文字列を返し、s1に代入されますが、 s2はs1の参照型であるため、「Hello!Java」から「Java」に 変わると思われます。実際には、 Java Java と、出力されると思われます。 以上、わかりにくい箇所があると思われますが、 ご教授の程お願い致します。

    • ベストアンサー
    • Java
  • Javaのプログラミングにおいて、暗黙的にオブジェクトが生成される場合はどんな場合ですか?

    Javaアソシエイツの資格取得ため、勉強しています。詳しい解説を求めています。 ■問題 次のプログラムを実行すると、出力結果はどのようになりますか。1つ選択してください。 http://d.hatena.ne.jp/motoi20/20081210 ■解説 正解は選択肢Aです。func(s)では、変数sが参照しているStringオブジェクトを「func(Stirng s)」の引数sに渡しています。func()メソッドの処理で「s+"Hello"」という処理をしたとき、内部では暗黙的に新しいStringオブジェクトが生成されます(変数sに文字列を追加しているわけではありません。)func()メソッドの呼び出しが「s=func(s)」となっていた場合、main()メソッド内の変数sが新しくできたオブジェクトを参照するため、結果の出力は「JavaHello」になりますが、「func(s)」の呼び出しでは戻り値を再代入していないため、変数sは文字列「Java」を保持したオブジェクトを参照します。Stringクラスは読み取り専用オブジェクトであることに注意しましょう。 ■疑問 通常、オブジェクトを作成するのは、「new」を使って行うわけですよね?暗黙的にオブジェクトが生成されるのは、どういう場合でしょうか?読み取り専用オブジェクトだから何に気をつければいいのでしょうか?

  • javaの参照渡しの問題

    javaの参照渡しの問題 javaの初心者で問題集で勉強しているのですが、 以下の問題の参照渡しの違いがわかりません。 ------------------------------------------- ソース1 class Samplea{ public void method(){ int b[] = new int[2]; set(b); System.out.println(b[0]); } public void set(int[] b){ b[0] = 30; } } class Sample{ public static void main(String srgs[]){ Samplea x = new Samplea(); x.method(); } } 実行結果 30 ------------------------------------------- ソース2 public class Test{ public static void main(String args[]){ String s1= "Hello"; String s2= "Good-Bye"; change(s1,s2); System.out.println(s1); } static void change(String s1,String s2){ s1 += ",Tom"; s1 = s2; } } 実行結果 Hello ------------------------------------------- 配列とString型は両方とも参照型なので ソース1の実行結果が「30」ならば、 ソース2の実行結果は「Good-Bye」になると思いました。 どなたか教えていただけないでしょうか。 宜しくお願いいたします。

    • ベストアンサー
    • Java
  • エクセル:複数セルからの参照

    お世話になります。 A,B,C列にデータが入っています。 D,E,F列に参照のためのデータがあります。 A,B,C列はそれぞれD,E,F列に対応しています。 A,B,C列と同じ並びのデータが入っている行をD,E,F列から探し、その隣のG列の値をH列に返す。 D,E,F列の並びが重複する行はありません。 A,D列は場所の名前、B,C,E,F列には数字が入っている。 例) A1に事務室 B1に20 C1に3 が入っているとする。 D/E/F列が 事務室/20/3 の並びになっているのが10行目の場合、H1にG10のセルの値を返す。 この場合、H列にはどんな計算式を入れておけばよいのでしょうか? A,B,C列と同じ並びのデータがD,E,F列で見つからない場合は空白をH列に返す。 ちなみにD/E/F列が 事務室/20/3 の並びになっている行は10行目しかないです。 よろしくお願いします。

  • C#で char型とstring型の比較で Equalsでハマりました。 

    C#で char型は値型でstring型は参照型ですがこの比較を正しく行うにはどうしたらよいでしょうか? string s = "0123456789"; Console.WriteLine(s[0]); Console.WriteLine("0".Equals(s[0]) ? "true" : "false"); で、falseなのは驚きでした。 Equalsを鵜呑みにしていました。 コンパイルできたので今まで気づきませんでした。 詳しい方、教えて頂けますか?

  • 文字制限節約のためimportは省きます

    文字制限節約のためimportは省きます public class MojiTest0621p2 { JFrame frame1; BufferStrategy bstrategy; int count =0; MojiTest0621p2(){     frame1=new JFrame("ゲームテスト"); frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame1.setBackground(Color.WHITE); frame1.setResizable(false); frame1.setVisible(true); Insets insets = frame1.getInsets(); frame1.setSize(600 + insets.left + insets.right,400 + insets.top + insets.bottom); frame1.setLocationRelativeTo(null);          frame1.setIgnoreRepaint(true); frame1.createBufferStrategy(2); bstrategy = frame1.getBufferStrategy(); Timer t=new Timer(); t.schedule(new MyTimerTask(),10,500); } public static void main(String args[]){ MojiTest0621p2 gtm =new MojiTest0621p2(); } class MyTimerTask extends TimerTask{ @Override public void run() { Graphics g=bstrategy.getDrawGraphics(); if(bstrategy.contentsLost()==false){ Insets insets=frame1.getInsets(); g.translate(insets.left,insets.top);//左上 文字は別 g.setColor(Color.BLUE); String sa = "Hello、Worldハローワールド"; // 文字列saを生成 String sb = "えんがち"; // 文字列sbを生成 String sc = "あつい"; // 文字列scを生成 int gyo1=0; int gyo2=0; int gyo3=0; String str1="Hello、Worldハローワールド"; String str2="えんがち"; g.setFont(new Font("SansSerif",Font.BOLD,20)); for(gyo1=1;gyo1<=sa.length();gyo1++){ String s1 = sa.substring(0 , gyo1); // 1文字目からi文字目を取得 g.drawString(s1, 100, 100); } if(str1.equals(sa)==true){ for(gyo2=1;gyo2<=sb.length();gyo2++){ String s2 = sb.substring(0 , gyo2); // 1文字目からi文字目を取得 g.drawString(s2, 100, 150); } } (str2.equals(sb)==true){ for(gyo3=1;gyo3<=sc.length();gyo3++){ String s3 = sc.substring(0 , gyo3); g.drawString(s3, 100, 200); } } bstrategy.show();} g.dispose(); } } } javaの質問です ノベルゲームのTimerTaskでオートモードを作りたいのですがうまく作れません。 Hello、Worldハローワールドを一文字ずつ毎秒ごとに描画し、読み終わったら えんがちを一文字ずつ描画するというプログラムを組みたいです。 上記のプログラムをベースに(でもいくらでも変えていいですよ)改善箇所、修復箇所を お願いします

    • ベストアンサー
    • Java
  • javaプログラムの質問です。お願いします

    1このプログラムの全てのインスタンス変数について、変数名を書いてください。 2全てのメソッド名を書いてください。 よろしくお願いします。 1: import java.awt.event.*; 2: import java.awt.*; 3: import java.io.*; 4: import java.net.*; 5: 6: public class Test71 { 7: private MyCanvas c; 8: public static void main( String[] args ) { 9: Test71 t71 = new Test71(); 10: t71.doEvent(); 11: } 12: 13: Test71() { 14: Frame f = new Frame( "Test71" ); 15: f.setSize( 640, 480 ); 16: f.addWindowListener( new WindowAdapter() { 17: @Override public void windowClosing( WindowEvent e ) { 18: System.exit( 0 ); 19: } 20: }); 21: c = new MyCanvas(); 22: f.add( c ); 23: f.setVisible( true ); 24: } 25: 26: public void doEvent(){ 27: try{ 28: ServerSocket ss = new ServerSocket( 8000 ); 29: while( true ) { 30: Socket socket = ss.accept(); 31: BufferedReader br = new BufferedReader( new InputStreamReader( socket.getInputStream() ) ); 32: BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( socket.getOutputStream() ) ); 33: while( true ) { 34: String command = br.readLine(); 35: String[] words = command.split( " " ); 36: System.out.println( command ); 37: if( words[0].equalsIgnoreCase( "setOval" ) ) { 38: try { 39: c.setPoint( Integer.parseInt( words[1] ), Integer.parseInt( words[2] ) ); 40: } catch( Exception e ) {} 41: } else if( words[0].equalsIgnoreCase( "changeMode" ) ) { 42: //描画方式を変更する処理 43: } 44: else if( words[0].equalsIgnoreCase( "quit" ) ) { 45: break; 46: } 47: } 48: bw.close(); 43 49: br.close(); 50: socket.close(); 51: } 52: } catch( Exception e ) { 53: e.printStackTrace(); 54: } 55: } 56: }

    • ベストアンサー
    • Java
  • javaのプログラミングについての質問です

    javaのプログラミングについての質問です 任意の複数の数値を入れたファイルを読み取りその数値の場所から次の数値まで線を描画するプログラミングを作成しました ここから発展問題としてタートルグラフィックスを 描画するプログラムを50歩進み右に90度曲がることを4度繰り返すという条件で作ってみようと思ったのですが上手くコンパイルが通りません 取りあえず分かっているのは (100.cos45,100.sin45)で90°曲がる repeat 4,forward 50right 90 end 0 だけです もし分かる方がいらっしゃいましたらご返答宜しくお願いします import java.awt.*; import java.awt.event.*; import java.io.*; public class mondai{ int x[] = new int[100]; int y[] = new int[100]; int len = 0; public static void main(String[] args){ new mondai(args[0]); } public mondai(String mondai2){ ReadFile rf = new ReadFile(mondai2); String line; while( (line = rf.gets()) != null) { String[] date = line.split(","); if(date.length == 2){ x[len] = Integer.parseInt(date[0]); System.out.println(date[0]); y[len]= Integer.parseInt(date[1]); System.out.println(date[1]); len++; } } Frame f = new Frame(); f.setTitle("Line"); f.setSize(640,480); f.setLayout(null); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); }}); DrawArea da = new DrawArea(); da.setBounds(0,0,640,480); f.add(da); f.setVisible(true); } private class DrawArea extends Canvas{ public void paint(Graphics g){ for(int i=0;i<len-1;i++) g.drawLine(x[i],y[i],x[i+1],y[i+1]); } } private class ReadFile{ FileInputStream fis; InputStreamReader isr; BufferedReader br; public ReadFile(String filename){ try{ fis = new FileInputStream(filename); isr = new InputStreamReader(fis); br = new BufferedReader(isr); }catch(Exception e){ e.printStackTrace(); } } public String gets(){ String line = ""; try{ line = br.readLine(); }catch(Exception e){ e.printStackTrace(); } return line; } } }

専門家に質問してみよう