javaの引数の引渡し作用についてよくわかりません


質問が連投になって大変申し訳ないのですが。  
javaを学習中でありますが、引数の引渡し作用がいまいちわかりません。

[code]

    class CallByValue{
    public static void main(String args[]){
        int i   = 5;
        int j[] = { 1, 2, 3, 4};
        StringBuffer sb = new StringBuffer("abcde");
    
        display(i, j, sb);
    
        a(i, j, sb);
    
        display(i, j, sb);
    }
    
    static void a(int i, int j[], StringBuffer sb) {
        i = 7;
        j[0] = 11;
        sb.append("fghij");
    }
    static void display(int i, int j[], StringBuffer sb) {
        System.out.println(i);
        for(int index = 0; index < j.length; index++)
            System.out.println(j[index] + " ");
        System.out.println("");
        System.out.println(sb);
    }}
    
[/code]

このコードで出されるメッセージは  
5  
1  
2  
3  
4

abcde  
5  
11  
2  
3  
4

abcdefghij  
です。  
main()で記述されている diplay()で一度表示して a()でstatic void a()の値を戻して変えて次の
display()に表示といった順にメッセージを表示していると考えているのですが

[code]

    static void a(int i, int j[], StringBuffer sb) {
        i = 7;
        j[0] = 11;
        sb.append("fghij");
    }
    
[/code]

このコードをみると 7 11 2 3 4 fghijとなるのではないかと思います。

i = 7と書いているのにどうして i=5のままで出されるのでしょうか  
またsb.append("fghij")と書かれているのにどうして abcdefghijと出されるのでしょうか。  
よろしくお願い致します。




Java の関数は値渡しになります。関数を呼び出す側から変数が渡されているのではなく値が渡されています。

[code]

    public class Foo {
        public static void foo() {
            int i = 0; // (1) i に 0 という値が格納される
            bar(i);    // (2) i の値が bar の引数として渡される
        }
        public static void bar(int n) {
            n = 1;     // (3) 値が渡されているだけなので変数の中身を更新しても意味が無い
        }
    }
    
[/code]

違う変数名を使うとイメージ湧きやすいと思います。  
ただし値渡しとはいっても渡される物が何かによって初心者の方が躓く結果が現れます。  
Java の Object を継承したインスタンスも同様に値が渡されます。

[code]

    class Boo {
        int n = 0;
        public void setValue(int n) { this.n = n; }
        public int getValue() { return this.n; }
    }
    
    public class Foo {
        public static void foo() {
            Boo b = new Boo(); // (1) b に Boo のインスタンスが格納される
            b.setValue(0);     // (2) 中身の値を更新する
            bar(b);            // (3) インスタンスという値が渡される
        }
        public static void bar(Bar b) {
            b.setValue(1);     // (4) b が変更されるのではなく
                               //     b から辿る事が出来る n が更新される。
            b = new Boo();     // (5) 変数を上書きしても (4) は壊れない。
        }
    }
    
[/code]

関数 foo が生成した b を引数経由で関数 bar に渡して更新し、関数 foo に戻す事は出来ませんが、b の中身を更新する事は出来ます。  
これはインスタンスだけでなく、例えば配列を渡して配列を丸ごと書き換えて戻す事は出来ないけれど、配列の中身を変えて戻すことは出来る、という意味と同じです。

上記の例だと i の値を変えても意味は無いですが、a から辿れる StringBuffer の中身を自身で更新する事は出来るのです。




Java の関数は値渡しになります。関数を呼び出す側から変数が渡されているのではなく値が渡されています。

[code]

    public class Foo {
        public static void foo() {
            int i = 0; // (1) i に 0 という値が格納される
            bar(i);    // (2) i の値が bar の引数として渡される
        }
        public static void bar(int n) {
            n = 1;     // (3) 値が渡されているだけなので変数の中身を更新しても意味が無い
        }
    }
    
[/code]

違う変数名を使うとイメージ湧きやすいと思います。  
ただし値渡しとはいっても渡される物が何かによって初心者の方が躓く結果が現れます。  
Java の Object を継承したインスタンスも同様に値が渡されます。

[code]

    class Boo {
        int n = 0;
        public void setValue(int n) { this.n = n; }
        public int getValue() { return this.n; }
    }
    
    public class Foo {
        public static void foo() {
            Boo b = new Boo(); // (1) b に Boo のインスタンスが格納される
            b.setValue(0);     // (2) 中身の値を更新する
            bar(b);            // (3) インスタンスという値が渡される
        }
        public static void bar(Bar b) {
            b.setValue(1);     // (4) b が変更されるのではなく
                               //     b から辿る事が出来る n が更新される。
            b = new Boo();     // (5) 変数を上書きしても (4) は壊れない。
        }
    }
    
[/code]

関数 foo が生成した b を引数経由で関数 bar に渡して更新し、関数 foo に戻す事は出来ませんが、b の中身を更新する事は出来ます。  
これはインスタンスだけでなく、例えば配列を渡して配列を丸ごと書き換えて戻す事は出来ないけれど、配列の中身を変えて戻すことは出来る、という意味と同じです。

上記の例だと i の値を変えても意味は無いですが、a から辿れる StringBuffer の中身を自身で更新する事は出来るのです。

