FC2ブログ
HOME   »  スポンサー広告  »  スポンサーサイト   »  Java  »  [Java]値渡しと参照渡し

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[Java]値渡しと参照渡し

引数の値渡しと参照渡しについて。

メソッドに引数を渡す際、booleanやint等の基本型(プリミティブ型)は値渡し、クラスインスタンス等の参照型(オブジェクト型)は参照渡しとなる。

○引数が基本型の場合
public class Main {
    public static void main(String[] args) {
        int i = 0;
        System.out.println("メソッドに渡す前の値:i = " + i);
        method(i);
        System.out.println("メソッドに渡した後の値:i = " + i);
    }

    private static void method(int i) {
        i = i + 1;
        System.out.println("メソッドで処理した後の値:i = " + i);
    }
}
3行目で変数iに0を代入し、5行目でmethodメソッドに引数として渡している。
methodメソッドの中では、仮引数iの値に+1している。

上記の実行結果は以下の通り。


メソッドに渡す前の値:i = 0
メソッドで処理した後の値:i = 1
メソッドに渡した後の値:i = 0


methodメソッドで処理した後のmethodメソッドの仮引数iの値は、渡された時の値0に+1しているので1となっている。
一方、methodメソッド呼び出し元の変数iの値は、methodメソッドに渡す前と後で変わらず0のままである。

呼び出し元の変数iとmethodメソッドの仮引数iは独立した別々の変数であり、それぞれ個別に値を持っている。
引数として渡す際には呼び出し元の変数iの値がmethodメソッドの仮引数iに代入され(値がコピーされ)、methodメソッド内での処理は仮引数iの値に対してのみの処理となる為、呼び出し元の変数iの値には影響を及ぼさない。

これが値渡しの場合の動作となる。

○引数が参照型の場合
まず、以下の様なクラスを作成する。
public class Hoge {
    public int i;

    public Hoge() {
        i = 0;
    }
}
そして、上記のHogeクラスを下記の様に使用してみる。
public class Main {
    public static void main(String[] args) {
        Hoge hoge = new Hoge();
        System.out.println("メソッドに渡す前の値:hoge.i = " + hoge.i);
        method(hoge);
        System.out.println("メソッドに渡した後の値:hoge.i = " + hoge.i);
    }

    private static void method(Hoge hoge) {
        hoge.i = hoge.i + 1;
        System.out.println("メソッドで処理した後の値:hoge.i = " + hoge.i);
    }
}
3行目でHogeクラスのインスタンスを生成し、5行目でmethodメソッドに引数として渡している。
methodメソッドの中では、引数として渡されたHogeクラスのインスタンスのフィールド変数iに+1している。

上記の実行結果は以下の通り。


メソッドに渡す前の値:hoge.i = 0
メソッドで処理した後の値:hoge.i = 1
メソッドに渡した後の値:hoge.i = 1


methodメソッドで処理した後のフィールド変数iの値は、渡された時の値0に+1しているので1となっている。
一方、methodメソッド呼び出し元のフィールド変数iの値は、methodメソッドに渡す前は0だが、渡した後は1となっている。

呼び出し元の変数hogeとmethodメソッドの仮引数hogeは独立した別々の変数であり、それぞれ個別に値を持っている(基本型と同じ)。
引数として渡す際には呼び出し元の変数hogeの値がmethodメソッドの仮引数hogeに代入される(ここも基本型と同じ)。
基本型と参照型で異なるのは、基本型が代入された値そのものを保持しているのに対して参照型は代入されたインスタンスの参照情報(どのインスタンスを指しているか)を保持している、という点である。

引数として渡す際に呼び出し元の変数から呼び出し先の仮引数に代入される(コピーされる)値はこのインスタンスの参照情報であり、インスタンスそのものではない。従って、呼び出し元の変数hogeが参照しているHogeクラスのインスタンスと呼び出し先の仮引数hogeが参照しているHogeクラスのインスタンスは同一である。
その為、methodメソッドでのフィールド変数iの処理=呼び出し元のフィールド変数iの処理となり、methodメソッドに渡す前と後で呼び出し元のフィールド変数iの値が変化することになる。

では、下記ではどうなるか。
public class Main {
    public static void main(String[] args) {
        Hoge hoge = new Hoge();
        System.out.println("メソッドに渡す前の値:hoge.i = " + hoge.i);
        method(hoge);
        System.out.println("メソッドに渡した後の値:hoge.i = " + hoge.i);
    }

    private static void method(Hoge hoge) {
        hoge = new Hoge();
        hoge.i = hoge.i + 1;
        System.out.println("メソッドで処理した後の値:hoge.i = " + hoge.i);
    }
}
上記の実行結果は以下の通り。


メソッドに渡す前の値:hoge.i = 0
メソッドで処理した後の値:hoge.i = 1
メソッドに渡した後の値:hoge.i = 0


上記の場合は、10行目でmethodメソッドの仮引数hogeに新たに生成したHogeクラスのインスタンスの参照情報を代入しており、この時点で呼び出し元の変数hogeと呼び出し先の仮引数hogeが参照しているHogeクラスのインスタンスが違うものになる
その為、methodメソッドでのフィールド変数iの処理は呼び出し元のフィールド変数iの値には影響を及ぼさない。

以上、基本型と参照型での動作の違いを書いたが、参照型でもStringではちょっと違った動作となる。
が、長文になってしまったのでそれは別の記事で。

ところで、ここまで散々「参照渡し」と書いてきたが実はJavaにあるのは「値渡し」だけで、「参照渡し」はない。
上に書いた通り参照型引数で渡されるのは「参照情報」であり、渡し方も実引数から仮引数への「参照情報のコピー」なので、正確にはこれも「値渡し」である。
参照型引数の動作を理解して明示的に「呼び出し元で生成したインスタンスと同一のインスタンスを呼び出し先で使用する」のを目的とするのであれば、便宜的に「参照渡し」と言っても大きな問題はないと思うが、「Javaには値渡ししかない」という点から参照型引数での「インスタンスのコピー」を期待すると想定外の動作となってしまうことがあるので注意が必要。


関連記事
Comment
Trackback
Trackback URL
Comment Form
管理者にだけ表示を許可する
プロフィール

まさお

Author:まさお
プログラミングは趣味レベルなので、お手柔らかに。

ブログランキング
ブログランキング参加中。是非クリックお願いします。


にほんブログ村 IT技術ブログ Androidアプリ開発へ

人気ブログランキングへ

ブログランキング



ブログ王

ブログランキング【ブログの惑星】

プログラム人気ブログランキング
最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム
QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。