• ベストアンサー

コンストラクタで設定した値が表示されない

以下のプログラムを見ていただけたら分かるとおり、コンストラクタで設定した値が、配列だと表示されるのに、配列を使用していない変数だと表示されません。なせなのでしょうか? よろしくお願いします。 package test; public class test { public test(int[] idt, double ddt, String title) { title = "テスト"; ddt = 99.9; for(int i=0; i<idt.length; i++) { idt[i] = i; } } public static void main(String[] args) { int[] idt = {0, 0, 0}; double ddt=0.0; String title= ""; test t = new test(idt, ddt, title); for(int i=0; i<idt.length; i++) { System.out.println(idt[i]); } System.out.println(ddt + ", " + title); } }

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

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

  • ベストアンサー
noname#49664
noname#49664
回答No.2

これは要するに、引数として渡した変数の値をコンストラクタ内で変更している(つもり)なのになぜ変わらないか?ということでしょうか。 Javaでは、「プリミティブタイプは値渡し、オブジェクトは参照渡し」というのが基本です。intやdoubleなどは、値を保管する場所を確保し、それがそのまま変数に設定されます。これが引数などで渡されるときには、その値のコピーがメモリ内に作成され、それがメソッドの引数として渡されるわけです。つまり、元の変数とメソッドに渡された変数は別のものです。したがって、コンストラクタ側でどんなに操作しようと、元の変数の値は変わりません。別のものなのですから当然です。  これに対し、オブジェクトは参照(インスタンスがある場所を示す情報)渡しです。インスタンスを作成して変数に代入するとき、Javaではメモリ内にインスタンスを生成し、そのインスタンスがある場所を示す「参照」を値として変数に設定します。  メソッドなどで引数としてインスタンスを渡す場合には、この参照の値を新たにコピーした変数が作成され、これが割り当てられることになります。これにより、どちらも同じインスタンスを参照する値であるため、同じオブジェクトをそのまま引き継いで操作できるわけです。  したがって、渡されたインスタンスをそのまま利用して操作する場合、どちらも同じインスタンスを参照していますから片方で変更したものはもう片方でも反映されます。なにしろ同じものなんですから。配列を引渡してその中身を操作した場合、コンストラクタ側で操作するとmain側の変数にある配列も変わってしまうのはそれが理由です。  が、どちらの変数も同じインスタンスを参照してはいますが、あくまで「インスタンスがある場所を示す値が同じ」というだけなので、片方の変数に別のインスタンスの参照を入れてしまえば、両者は別のものを示すことになり、片方でインスタンスを変更してももう片方には反映されなくなります。  それが、Stringで値が反映されない理由です。コンストラクタ側の変数に新しいStringを代入した段階で、別のオブジェクトを参照するようになってしまっているのです。title = "テスト";というのは、いってみればtitle = new String("テスト");としているのと同じようなものです(正確には違いますが)。  ということは、メモリ内に新たに"テスト"というインスタンス(正確にはリテラル)を作成し、それを参照する値をtitleに代入する(つまり、この段階でmain側の変数とは別のオブジェクトを参照するようになっている)わけです。だから、コンストラクタ側が"テスト"になっているのに、main側は""のままなのです。 このあたりは、実際にいろいろと試してみるとなんとなくわかってきますよ。例えばですが。 String A = "Hello"; String B = A; A = "Bye"; これで変数Bの値はどうなるでしょうか? "Hello"になるはずですね。Aを"Bye"にしたからといって、Bも"Bye"にはなりません。なぜなら、A = "Bye"とした段階で、AにはBとは別のStringへの参照が設定されるために、両者は別々のStringを指し示すようになるからです。  では、今度はどうでしょう。 StringBuffer A = new StringBuffer("Hello"); StringBuffer B = A; A.delete(0,A.length()).append("Bye"); これで変数Bの値はどうなるでしょうか。実は、"Bye"になります。今回は、変数BにAと同じStringBufferを参照し、そのインスタンス自体を操作することで値を変更しています。新たな値を代入はしていません。したがって、最後まで変数AとBは同じインスタンスを参照することになり、Aを変更するとBも同じように変わるのです。  この両者の違いがわかるようになれば、疑問はとけると思いますよ。

kamakuragengorou
質問者

お礼

遅くなってしまい申し訳ありません。 丁寧かつ詳しく、このような長文で大変だったと思います。ご返答ありがとうございます。 >「プリミティブタイプは値渡し、オブジェクトは参照渡し」 これをJavaをやり始めた1年前に、本で読んだ記憶があります。しかしすっかり忘れていました。 おかげさまで思い出すことができ、その当時の謎も解き明かすことが出来ました。 ありがとうございました。

その他の回答 (3)

  • tom11
  • ベストアンサー率53% (134/251)
回答No.4

こんにちは、 書き換えてみました。 public class test { int [] idt; double ddt; String title; /** Creates a new instance of test */ public test(int []idt,double ddt,String title) { this.idt = new int[idt.length]; for(int i=0;i<idt.length;++i){ this.idt[i] = idt[i]; } this.ddt = ddt; this.title=title; } /** * @param args the command line arguments */ public static void main(String[] args) { int [] idt ={0,0,0}; test t = new test(idt,0.0,"テスト"); for(int i=0;i<t.idt.length;++i){ System.out.println(t.idt[i]); } System.out.println(t.ddt+","+t.title); //追加オブジェクト int [] idt1={1,2,3,4}; test t1 =new test(idt1,100.0,"テスト1"); for(int i=0;i<t1.idt.length;++i){ System.out.println(t1.idt[i]); } System.out.println(t1.ddt+","+t1.title); // TODO code application logic here } } こんな感じのほうが良いと思いますよ。

kamakuragengorou
質問者

お礼

遅くなってしまい申し訳ありません。ご返答ありがとうございます。 いつも丁寧なサンプルコードを示していただきありがとうございます。そういえばフィールドを用いて、「インスタンス.フィールド」で、そのクラスの変数をそのまま使うことが出来ましたよね。 ありがとうございました。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

コンストラクタでどうしてそのような副作用が必要なのかよくわかりませんが、 通常、参照型でないもの(double とかの基本データ型)を関数に渡す時には、関数にはそのコピーが渡されますので、 元の変数の内容は変更されません。

kamakuragengorou
質問者

お礼

遅くなってしまい申し訳ありません。簡潔で分かりやすいご返答ありがとうございます。 昔Javaを入門するときに読んでいたはずなのですが、すっかり忘れていました。このような基本的なことなのにすみません。 ありがとうございました。

noname#18558
noname#18558
回答No.1

配列やオブジェクトは参照渡しなので、メソッドやコンストラクタ内部で引数の内容を変更すると変わってしまいます。 一方、プリミティブ型は値渡しなので、変更されません。 参照渡しや値渡しはJavaに限らずプログラミングの基本なので覚えておいたほうがいいと思います。

kamakuragengorou
質問者

お礼

遅くなってしまい申し訳ありません。ご返答ありがとうございます。 そういえば昔Javaの本を読んでいたときに参照渡しや値渡しを見たことがありました。すっかり忘れてしまっていて、このような質問をしてしまいました。すみません。 ありがとうございました。

関連するQ&A

  • booleanの戻り値について

    配列の等価判定をしたいのですが思うように動かないです。 助けてください import java.io.*; class Kadai4 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int[] TBL1; int[] TBL2; TBL1 = new int[5]; TBL2 = new int[5]; boolean flg=true; System.out.println("配列1を入力"); for (int i = 0; i <= 4; i++) { String s1 = br.readLine(); int t1 = Integer.parseInt(s1); TBL1[i] = t1; } System.out.println("配列2を入力"); for (int i = 0; i <= 4; i++) { String s1 = br.readLine(); int t1 = Integer.parseInt(s1); TBL2[i] = t1; } // 配列表示 System.out.println("配列表示"); for (int i = 0; i < TBL1.length; i++) { System.out.print(" TBL1[" + i + "]=" + TBL1[i]); } System.out.println(""); for (int i = 0; i < TBL2.length; i++) { System.out.print(" TBL2[" + i + "]=" + TBL2[i]); } toka(TBL1, TBL2); System.out.println(""); if (flg == true) { System.out.println("配列は等価"); } else { System.out.println("配列は非等価"); } } private static boolean toka(int[] ss1, int[] ss2) { boolean flg = true; for (int i = 0; i < ss1.length; i++) { if (ss1[i] != ss2[i] || ss1.length != ss2.length) { flg=false } } return flg; } }

  • 配列のコピーをして値を返したいが

    //配列のコピーをして値を返したい import java.util.*; public class Test7_22 { static int[] arrayClone(int[] a){ int[] b = new int[a.length]; for(int i =0;i>a.length;i++) b[i] = a[i];//ここで代入されるはず return b; } public static void main(String[]args){ Scanner std = new Scanner(System.in); System.out.print("要素数:"); int n = std.nextInt(); int[] a = new int[n]; for(int i=0;i<n;i++){ System.out.print("a["+i+"]="); a[i] = std.nextInt(); } int[] x = arrayClone(a); for(int i=0;i<a.length;i++) System.out.println("x["+i+"]="+x[i]); } } //コンパイルするとb[0] = 0になる

    • ベストアンサー
    • Java
  • GUI~ボタン処理~

    このプログラムはファイル操作を使ったプログラムです。 import java.io.*; class k203 { public static void main(String args[]) throws IOException { int num,max,test[][]; double sum[]; String name[]; String Subj[] = {"国語","数学","社会","理科","英語"}; num = Read.readInt("人数"); test = new int[num][Subj.length]; sum = new double[Subj.length]; name = new String[num]; for(int i=0; i<num; i++) { System.out.print( (i+1)+"人目の名前:"); name[i] = Read.readString(); } System.out.print("\n"); for(int i=0; i<num; i++) { System.out.println(name[i]+"さんの点数"); for(int j=0; j<Subj.length; j++) { test[i][j] = Read.readInt(Subj[j]); sum[j] += test[i][j]; } } System.out.print("\n"); for(int j=0; j<Subj.length; j++) { max = 0; for(int i=0; i<num; i++) { if(test[i][j]>test[max][j]) { max = i; } } System.out.println(Subj[j]); System.out.println("最高点:"+test[max][j]+" "+name[max]+"さん"); System.out.println("平均点:"+sum[j]/num); System.out.print("\n"); } } } このプログラムをGUIをつかってボタンをクリックすると実行できるように したいのですがどんな感じにすればよいか教えてください!

    • ベストアンサー
    • Java
  • JAVAコンストラクタについて

    JAVA のコンストラクタ定義の際に、下記のようにコンストラクタにvoidを付けた時と付けない時の処理結果が変わるのはなぜでしょうか。 (1) class O { protected int d; O(){ System.out.println("O = " + d); } } class Study_6_3main_void { public static void main(String args[]) { int i = 1; O OO = new O(); System.out.println("O = "); } } (2) class O { protected int d; void O(){ System.out.println("O = " + d); } } class Study_6_3main_void { public static void main(String args[]) { int i = 1; O OO = new O(); System.out.println("O = "); } } 実行結果 (1) O = 0 O = (2) O = 以上です。回答の程よろしくおねがいします。

    • ベストアンサー
    • Java
  • Javaコンパイルエラー

    Javaにて以下のようなプログラムを作成していますが、 「演算子 ^ は引数の型 double, int で未定義です。」とエラーになりました。 色々な方のご協力もあり、ここまで作れましたが、 これより先が行き詰っています。 教えていただけないでしょうか。 ---------------------------------------------- // 分散を返すメソッド public class Kadai16 { public static void main(String args[]){ //double型の配列の生成 double[]a=new double[10]; argument(a); //配列aの要素[0]から[9]の内容を表示 System.out.println(a[0]); System.out.println(a[1]); System.out.println(a[2]); System.out.println(a[3]); System.out.println(a[4]); System.out.println(a[5]); System.out.println(a[6]); System.out.println(a[7]); System.out.println(a[8]); System.out.println(a[9]); //double total=sum(a)を実行する double total =sum(a); System.out.println("合計は"+total+"です。"); //使って平均を出す double heikin; mean(total); heikin = mean(total); System.out.println("平均は"+heikin+"です。"); //分散を返す double bunsan; bunsan = total-heikin^2/10; System.out.println("分散は"+bunsan+"です。"); } /** * ランダムな数値を入れるメソッド * @param a ランダムな数値を入れる配列 */ private static void argument(double[]a) { //引数の配列aの[0]から[9]までランダムな数値を設定する。 for(int i=0; i<a.length;i++) { a[i]=Math.floor(Math.random()*10); } } //配列を受け取って要素の合計を出すメソッド public static double sum(double[] x) { double t=0; for(int i=0; i<x.length;i++) { t= x[i]+t; } return t; } //配列を受け取って平均を出すメソッド public static double mean(double b) { return b/10; } //分散を返すメソッド public static double bunsan(double c) { double t=0; double bnsan =0; for(int i=0; i<c.length; i++) { t =c[i]+t } } }

  • Java trimの設定について

    Java trimの設定についてお伺いいたします。 最高気温と最低気温を表示することができずに困っております。trimをどのように設定すれば良いかご教授お願いします。 以下、ソースを記載します。 import java.io.*; public class Sample { public static void main(String[] args) { try{ BufferedReader br = new BufferedReader(new FileReader("kion.txt")); System.out.println("気温データ出力"); int test[] = new int[4]; String str; for(int i=0;i<test.length;i++){ str = br.readLine(); } int max = 0; int min = 0; for(int i=0;i<test.length;i++){ if(max < test[i]) max = test[i]; if(min > test[i]) min = test[i]; System.out.println(test[i]); } System.out.println("最高気温" + max + "です。"); System.out.println("最低気温" + min + "です。"); br.close(); } catch(IOException e){ System.out.println("入出力エラーです"); } } } また「kion.txt]は 東京 30.2 18.5 神奈川 34.2 18.5 埼玉 29.8 16.4 千葉 27.5 14.7 と作成しました。 これを 最高気温 神奈川 34.2 最低気温 千葉  14.7 と表示したいのですが、現在は「0 0 0 0」と表示するだけです。 何卒、よろしくお願い致します。

  • 並び換えるクラスについて

    小さい順に並べかえをテストするクラスが下のように指定されている場合、 小さい順に並べかえ処理をするクラスはどのようにすればいいのでしょう? class SortTest{ public static void main(String[] args){ int[] arri = {3, 2, 8, 7, 4, 6, 1, 0, 5, 9}; System.out.println(); System.out.print("\tソート前:"); arrayPrintln(arri); tool.Sort.ascendBubble(arri); // クラスメソッドに処理を委譲 System.out.print("\tソート後:"); arrayPrintln(arri); System.out.println(); double[] arrd = {3.3, 2.2, 8.8, 7.7, 4.4, 6.6, 1.1, 0.0, 5.5, 9.9}; System.out.println(); System.out.print("\tソート前:"); arrayPrintln(arrd); tool.Sort.ascendBubble(arrd); // クラスメソッドに処理を委譲 System.out.print("\tソート後:"); arrayPrintln(arrd); System.out.println(); } //配列の値を出力するメソッド******************* public static void arrayPrintln(int[] arr){ for(int i=0; i<arr.length; i++){ System.out.print(arr[i] + " "); } System.out.println(""); } public static void arrayPrintln(double[] arr){ for(int i=0; i<arr.length; i++){ System.out.print(arr[i] + " "); } System.out.println(""); } } 初心者な私がggったりして作成したやつが↓です。 class Sort{ public ascendBubble(int[] arri); public ascendBubble(double[] arri); //public void getArri(){ //public void getArri(String[] arri){ public void getArri(int[] arri){ for(int i=0;i<arri.length-1;i++){ for(int j=arri.length-1;j>i;j--){ if(arri[j]<arri[j-1]){ int t=arri[j]; arri[j]=arri[j-1]; arri[j-1]=t; } } } } public void getArri(double[] arri){ for(int i=0;i<arri.length-1;i++){ for(int j=arri.length-1;j>i;j--){ if(arri[j]<arri[j-1]){ int t=arri[j]; arri[j]=arri[j-1]; arri[j-1]=t; } } } } } わかりずらいかと思いますが、 アドバイスの方よろしくお願いします。

  • osamuyさん、では「今まで入力した人数分のの平均」と「10人分の平

    osamuyさん、では「今まで入力した人数分のの平均」と「10人分の平均」とはどう違うのですか。やっぱりforループが関係しているのですか? ・「今まで入力した人数分の平均」 double avg=0; for(i=0; i<test.length; i++){ System.out.print((i+1)+"番は?"); String str = br.readLine(); int a = Integer.parseInt(str); test[i]=a; sum+=a;               avg = (double)sum/10; }          System.out.println("平均点は"+avg); ・「10人分の平均」          double avg=0; for(i=0; i<test.length; i++){ System.out.print((i+1)+"番は?"); String str = br.readLine(); int a = Integer.parseInt(str); test[i]=a; sum+=a; } avg = (double)sum/10; System.out.println("平均点は"+avg);

    • ベストアンサー
    • Java
  • Javaのオーバーロードを使った問題

    class Book{ String title, size; int price; Book(String title, String size, int price){ this.title = title; this.size = size; this.price = price; } public String info(){ return title + " " + size; } public String info(String title){ return title + " " + size + " " + price +"円"; } public int info(String title, String size){ return price; } } ________________________________________________________ class Book_test{ public static void main(String[] args){ String[] title = {"図鑑","参考書","雑誌","地図"}; String[] size = {"B4", "A5", "A4", "A3"}; int[] price={4500, 1800, 600, 1400}; Book[] b = new Book[4]; for(int i=0; i<b.length; i++){ b[i] = ****; } for(int i=0; i<b.length; i++){ System.out.println(***); } for(int i=0; i<b.length; i++){ System.out.println(***); } for(int i=0; i<b.length; i++){ System.out.println(***); } } } 実行結果は、以下の通り 図鑑 B4 参考書 A5 雑誌 A4 地図 A3 図鑑 B4 4500円 参考書 A5 1800円 雑誌 A4 600円 地図 A3 1400円 4500 1800 600 1400 このように表示するために、javaのソースコードを書かなくてはならないのですが、***の部分に何を入れれば良いのか分かりません。 特に、for文の部分です。 classが苦手なので分かりやすく教えていただけると幸いです。

    • ベストアンサー
    • Java
  • 2つの配列を1つの配列にする。

    JAVA初心者です。1日に何度も質問してしまってすいません。 問題 private static int[] concat(int[] ia1, int[] ia2) のメソードを使いarray1とarray2[の2つの配列が両方intのとき、array1 array2と続く配列を表示する。 private static int[] concat(int[] ia1, int[] ia2) { int e; for (e=0; e < ia1.length; e++) { } for (e=0; e < ia2.length; e++) { }     return new int[0]; } public static void main(String[]args){ int[] testIntArray1 = {1, 2, 8, 4}; int[] testIntArray2 = {99, 88, 77, 66}; // You should also test the case where the first // array is empty, the second array is empty, and // both arrays are empty. System.out.println("First test array for concat is: "); int e; for (e=0; e < testIntArray1.length; e++) { System.out.print(testIntArray1[e] + " "); } System.out.println(); System.out.println("Second test array for concat is: "); for (e=0; e < testIntArray2.length; e++) { System.out.print(testIntArray2[e] + " "); } System.out.println(); int[] result = concat(testIntArray1, testIntArray2); System.out.println("Result of concat is: "); for (e=0; e < result.length; e++) { System.out.print(result[e] + " "); } System.out.println(); //*********************************************************** 結果 First test array for concat is: 1 2 8 4 Second test array for concat is: 99 88 77 66 Result of concat is: 1 2 8 4 99 88 77 66 ←2つの配列分の値。 メインはなんとかできたのですが、まだ始めたばかりで配列などの仕組みも基本的なことしか分りません。どのようにしたら2つの配列をひとつの配列に1番目の配列、2番目の配列の順に収める事ができるのでしょうか。キーワードなどのアドバイスよろしくお願いします。

    • ベストアンサー
    • Java

専門家に質問してみよう