• ベストアンサー

オブジェクトの参照渡しについて

メソッドの引数にオブジェクトを指定した場合、 それは「参照渡し」だと理解していました。 でも以下のプログラムでは、指定したオブジェクトに変化がありません。 public static void main(String[] args) { BigDecimal b = new BigDecimal(1); System.out.println(b); test(b); System.out.println(b); } public static void test(BigDecimal b) { b = new BigDecimal(2); } 出力は以下です。 ------------------------- 1 1 ------------------------- どういうことでしょうか? 正しい知識をお教えください。 よろしくお願いします。

  • Java
  • 回答数5
  • ありがとう数1

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

  • ベストアンサー
  • hori1978
  • ベストアンサー率100% (1/1)
回答No.5

public static void test(BigDecimal b) { b = new BigDecimal(2); } この部分でnewされていますので、bの参照先があたらしいオブジェクトを参照するようにかわるはずですよね。そう考えてしまうのはわかります。 変数名がmain関数内と同じなので説明がしづらいので、下記のように変更させてください。 public static void main(String[] args) { BigDecimal mainb = new BigDecimal(1); System.out.println(mainb); test(mainb); System.out.println(mainb); } public static void test(BigDecimal testb) { testb = new BigDecimal(2); } ここでtestbとmainbは同じアドレスであると思ってしまうと、勘違いしてしまいます。あくまでtestbとmainbはおなじアドレスを「参照している」のであり、同じアドレスではありません。 局所的に説明すると下記のような感じです。 ------------- mainb : 5454363 ------------- testb : 5454363 ------------- 5454363 : 1 ------------- それをもって、 test関数内でtestbに新しいnew BigDecimalをおこなっても、 testbのアドレス参照先がかわるだけで、mainbにはなんの変更も行われません。 この説明でわからない場合は参考URLを読んでみてください。

参考URL:
http://www.tec-q.com/note/2007/04/_java_13.html

その他の回答 (4)

  • zozy
  • ベストアンサー率60% (20/33)
回答No.4

>指定したオブジェクトに変化がありません。 そもそも別のオブジェクトを参照しています。 このような場合は"フィールド変数"を使いましょう。 "フィールド変数"はひとつのクラス内で共通に使える変数です。 そして、メソッドの引数として宣言するのは "局所変数"といいそのメソッド内でしか使えません。 つまり,"局所変数のb"と"フィールド変数のb"は別物となります public class Test{ //フィールド変数 private static BigDecimal b; public static void main(String[] args){ b=new BigDecimal(1); System.out.println(b); test(b); System.out.println(b); } //メソッドの引数bは局所変数 //当メソッドの外では使えない public static void test(BigDecimal b){ //なのでTestクラスのフィールド変数bを参照 Test.b=new BigDecimal(2); } }

回答No.3

メソッドの仮引数に格納されるのは、あくまで実引数のコピー。 つまりそういう意味では「値渡し」です。 ここでは引数にオブジェクトすなわち参照型の値を受け渡しされているけれど、int型などのプリミティブな値を受け渡しする場合と機構的には同じだと考えればよいと思います。

回答No.2

一旦Javaは忘れてC言語へ。 間違っていたら指摘よろしくお願いします>識者様 int main(){ int i = 5; func(i); printf("%d",i); //5 } void func(int a){ // mainのiとaは同じ値が違う領域に入っている。== 値渡し a = 3; } =========================== int main(){ int * x; // int *型。実際には無いと思うけど,JavaのGenerics使ってpointer<T> で Tがintになっているって説明した方が解る? x = (int *)malloc(sizeof(int)); //メモリの領域にint型の大きさの部分が確保され,そのアドレスが返る。 //実際には確保しようとしたらメモリ不足だった、ということもあるが,その処理は書かない。 *x = 10; //アドレスの指す先の領域(int型)に値を代入。 func(x); printf("%d",i); //20 free(x); //確保した領域を解放。 } void func(int * a){ *a = 20; } 全く同じ。mainのxとaも同じ値(int *のアドレス)が違う領域に入っている。 アドレスが指す領域(int型)は同じ。 int *型の値渡し == int 型の参照渡し *aに20を突っ込んだから20が表示された。 *aではなくaに別の値を突っ込んだ場合, aは変わるが,*aの内容は変わらない。→xは元の値を保ったまま。*xの値も変わらない。

  • notnot
  • ベストアンサー率47% (4848/10262)
回答No.1

元のオブジェクトを書き換えてませんよね? bがBigDecimal(1)を指していたところに、別途BigDecimal(2)のオブジェクトを作って、bがそっちを指すようにしただけ。

関連するQ&A

  • 参照・値渡しについて

    下記プログラム(ソース1)を実行すると「1」という値が出力されます。しかし、2行目をprivate static int a;とすると「0」という値が出力されます。 オブジェクトは参照渡しで基本データ型は値渡しと思ったのですが、2行目の値をString型で行ったところ全く変更されていない値が出力されました。(ソース2) 一体どういうことでしょうか? 回答のほどよろしくお願い致します。 (ソース1) public class X{ private static int a[] = new int[1]; public static void main(String []args){ modify(a); System.out.println(a[0]); } public static void modify(int a[]){ a[0]++; } } (ソース2) public class X{ static String a = "a"; public static void main(String []args){ modify(a); System.out.println(a); } public static void modify(String a){ a = "b"; } }

    • ベストアンサー
    • Java
  • 参照渡し?

    お世話になります。 下記のソースを実行すると public class ExecMain { public static void main(String[] args) { ObjectLife obj = new ObjectLife(); ObjectLife obj2 = obj; obj = null; System.out.println(obj); System.out.println(obj2); } static class ObjectLife { public ObjectLife() { create(); } public void create() { System.out.println("create calling"); } public void destroy() { System.out.println("destroy calling"); this = null; } } } -------------------- create calling null objectLife.ExecMain$ObjectLife@1b90b39 という実行結果になりました。 「objectLife.ExecMain$ObjectLife@1b90b39」 がnullにならないのはどうしてなのでしょう? また this=null; で自分自身のインスタンスをnullにしようとおもったのですが コンパイルはとおるのですが実行してもなにもおきていないようです。 これはどのように解釈すればよいのでしょうか? 以上よろしくお願いいたします。

    • ベストアンサー
    • Java
  • 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
  • Javaの参照渡し

    以下のようなプログラムで望むような結果(下に書いてある実行結果)は得られるでしょうか。 class HelloWorld {   public static void main(String[] args)   {     String str;     makeString1(str);     System.out.println(str);     makeString2(str);     System.out.println(str);   }   public static void makeString1(String str)   {     String words = "HelloWorld!";     str = words;   }   public static void makeString2(String str)   {     str = "HelloWorld!!";   } } ---実行結果--- HelloWorld! HelloWorld!!

    • ベストアンサー
    • Java
  • 非staticフィールドを参照できない理由とは

     java勉強中です、宜しくお願いします。  下のようなプログラムを書き「Test1」をコメントアウトしたら、 「非staticフィールドをstatic参照できません。」というエラーが 出ました。  「Test1 t」をグローバル変数で定義したのですが、やはりを 「static」からは見れないということでしょうか。  「main」は特別な関数というのは分るのですが、staticフィールドとか クラスオブジェクトしか、main()からは覗けないという設計思想(?) とかはどのようなものなのでしょうか。  逆に覗けるのが可能ならばどのような不都合が生じるのでしょうか。  何かしら非常に不便を感じて使い勝手が悪いという気がして仕方ない のですが、特別にこうしなけらばならないとか、今までの他の言語であ った不具合(ex 隠蔽機能)を更に強化したためとかと言う理由があるの でしょうか。  ========================================================== public class Test1 { Test1 t; void calc() { int a = 2; int b = 3; System.out.println(a+b); } public static void main(String args[]) { /*Test1*/ t = new Test1(); t.calc(); } }

    • ベストアンサー
    • Java
  • 引数を指定しなければならないサンプルプログラムをeclipseでデバッグする方法について

    お世話になります。 表題のとおりなのですが、Allin one eclipse 3.5.0の環境に於いて引数を指定しなければならないサンプルプログラムを実行すると、本来なら引数を聞いてこなければならないところ、そのような振る舞いもなくエラーになります。 サンプルプログラムは以下の内容となります。 class List1{ public static void main(String[] args){ //1つ目の引数args[0]を表示します System.out.println("1つ目の引数:" + args[0]); //2つ目の引数args[1]を表示します System.out.println("2つ目の引数:" + args[1]); } } どなたか問題点がわかる方、ご教示願います。 よろしくお願いします。

  • 例外を明示的にthrowするとき

    例外をthrowしたいとき、以下の場合、IllegalArgumentException、FileNotFoundException、どちらを使用していいのかわかりません。 public static void main(String[] args){ try{ AAA(new File(args[0])); }catch(FileNotFoundException e){ System.out.println(e.getMessage); } e)catch(IllegalArgumentException e){ System.out.println(e.getMessgae()); } } public static void AAA(File file){ if(isFile()){ //処理 }else{ throw new IllegalArgumentException("引数が不正です");    //それともthrow new FileNotFoundException("ファイルが存在しません"); } }

  • 足し算するプログラム

    タイトルの通りですが足し算をするプログラムを書いてみました。 第一引数を第二引数を足し算するのですが引数に「001」や「002」などの数字が入力された時に足し算した結果として素直に「00*」と足し算が出来ません。何かいい方法は無いでしょうか?教えてください。 import java.text.*; class Tashizan { public static void main(String[] args) { try { if(args.length == 0) { System.out.println("引数を整数値で入力して下さい。"); } else if(args.length == 1) { System.out.println("引数を整数値で2つ入力して下さい。"); } else if(args.length == 2) { int a = Integer.parseInt(args[0]); int b = Integer.parseInt(args[1]); if(a <= 999999999 && b <= 999999999) { int wa = a + b; System.out.println(a + "+" + b + "の和は" + wa + "です。"); } else { System.out.println("入力した桁数を9桁以下か確認してください。"); } } else { System.out.println("引数は整数値で2つ入力して下さい。"); } } catch(NumberFormatException nfe) { System.out.println("整数値を2つ入力して下さい。"); } catch(Exception e) { System.out.println(e + "エラー発生!処理を終了します。"); } } }

    • ベストアンサー
    • Java
  • コマンドライン引数の*(アフタリスク)の表示について教えて下さい

    皆様どうぞよろしくお願い申し上げます。アドバイス下さい。 java言語で質問です。調べたかぎりわからないことが起こりました。次のものです。コマンドライン引数で引数1は数字、引数2は数字、引数3は* で表示させるプログラムを作りました。引数3番目の演算子*(アフタリスク)を表示する場合にうまく表示できません。 C:\java>java test 2.0 15.0 * 2.0 15.0 Calculation.class ←表示されません。 プログラムは以下のものを作りました。見てください。 /** * 実行クラス:引数テストクラス */ class test{ public static void main(String args[]) { //引数を取得 double num1 = Double.parseDouble(args[0]); //引数1(数値) double num2 = Double.parseDouble(args[1]); //引数2(数値) String kigou = args[2]; //引数3(計算記号) //画面に出しています。 System.out.println(num1); System.out.println(num2); System.out.println(kigou); } }

  • throw文について

    上と下のソースプログラムがよく似ているのにもかかわらず上記のプログラムでコンパイルエラー発生する理由がわかりません。 解決方法はpublic static void badMethod()throws IOException{に書き換えるということが分かっていますがイマイチ理屈が分からない次第であります。 たぶん、上記のプログラムはimport文があるからだと思うのですが回答のほどよろしくお願い致します。 (コンパイルエラー) import java.io.IOException; class TryCatch{ public static void main(String args[]){ try{ badMethod(); System.out.println("A"); } catch(IOException ex){ System.out.println("B"); } catch(Exception e){ System.out.println("C"); } System.out.println("E"); } public static void badMethod(){ throw new IOException(); } } (コンパイル正常) public class X{ public static void main(String args[]){ try{ badMethod(); System.out.println("A"); } catch(Exception ex){ System.out.println("B"); } finally{ System.out.println("C"); } System.out.println("D"); } public static void badMethod(){ throw new RuntimeException(); } }

専門家に質問してみよう