0

これは私が持っているコードです。質問を読む前にそれを見てください

 package ict201jansem2012;


public class Qn3b {

    public static void main(String[] args) {
        int a = 1;
        int b[] = {4,5};
        String s = "Good luck!";
        method1(b[1]);
        System.out.println("(1) b[0] = "+b[0]+"; b[1] = "+b[1]);
        method2(b);
        System.out.println("(2) b[0] = "+b[0]+"; b[1] = "+b[1]);
        method3(a);
        System.out.println("(3) a = " + a );
        method4(s);
        System.out.println("(4) s = " + s );
    }
    public static void method1(int b) {
        b = 7;
    }
    public static void method2(int[] b) {
        b[0] = 3;
    }
    public static void method3(int a) {
        a = 3;
    }
    public static void method4(String s) {
        s = "UniSIM";
    }
}

出力:(1)b [0] = 4; b [1] = 5

(2)b [0] = 3; b [1] = 5

(3)a = 1

(4)s =頑張ってください!

だから私の質問は、これは私が学習プログラマーとして知っているのは興味深いことです。int b配列0のインデックス値は変更されましたが、Stringsやintaなどの他の変数は変更されていません。このプログラムを実行する前に、メソッドが呼び出されると変数の値が変わることを大まかに考えました。これは、メソッドが呼び出され、a、s、b配列などの変数のメインメソッドが渡されたためです。変更されています。

つまり、一言で言えば、他の変数が変更されていないのに、b配列0のインデックスが変更されているのはなぜですか?

4

4 に答える 4

3

あなたは初心者プログラマーだと言ったので、何が起こっているのかを正確に説明する(または説明しようとする)ために少し記事を書きます。

これは、 method1 - method4メソッドに引数を渡しているためです。

これらの引数自体は、他のオブジェクトへの参照です。

等号である代入演算子を使用すると、現在のスコープ内の値の参照が上書きされます。ここで、変数は「表示」できます。

あなたのコードでは:

新しい参照を作成しているmethod1の場合、変数はそのスコープ内でのみ表示できます。つまり、次にb = << expr >>に移動すると、メソッド1のスコープ内の変数bに、メインスコープのbではなく値が割り当てられます。method3およびmethod4メソッドについても同じことが言えます。元のオブジェクトを変更するのではなく、新しい参照を作成するため、そのスコープのそれぞれの変数に新しい値を割り当てます。

ただし、me​​thod2のコードの動作は異なります。これは、そのコード内のオブジェクトを変更しているためです。そのスコープ内に新しい参照を作成するのではなく、オブジェクトを直接変更しています。

以下のコードを検討してください

int[] array = new int[] {1, 2};

public void test()
{
    method1(array);
    System.out.println(array[0] + ", " + array[1]);
    method2(array);
    System.out.println(array[0] + ", " + array[1]);
}

//  because we are working with objects, the identifier, can be different to the arrays identifier
//  in this case, I've chosen to use 'a' instead of 'array' to show this
public void method1(int[] a)
{
    //  this mutates the array object
    a[0] = 2;
}

public void method2(int[] array)
{
    //  this overwrites the method2.array but not the global array
    array = new int[] { 1, 2, 3 };
}

グローバルスコープに識別子'array'を使用して、新しい配列を作成します。(Javaでは、これはクラス独自のスコープになります)

method1では、引数を取ります。これは、グローバル配列オブジェクトとして渡されるオブジェクトと同じであるため、それを変更すると、両方のオブジェクトが変更されます。したがって、最初の印刷ステートメントは次のようになります

「2、2」

array[0]が変更された場所

注意:オブジェクトを処理するため、変数の「名前」は重要ではありません。同じオブジェクトへの参照のままです。

ただし、me​​thod2では、 method1と同様に引数を取りますが、今回は代入演算子を使用して、その変数を現在のスコープ内の新しい値に割り当てます。つまり、グローバル配列は変更されないため、引き続きプリントアウト

「2、2」

初心者プログラマーの場合、変数とスコープがどのように機能するかを完全に理解できるいくつかのテストプログラムを個人的に作成します。

ただし、新しいコードブロックを作成するたびに、新しいスコープが作成され、そのスコープへのローカル変数は、そのスコープとその下のスコープでのみ表示されます。

例えば:

public void test()
{
    int a = 5;
    method1(a);
    System.out.println(a);  //  prints 5
}

public void method1(int a)
{
    // a is only viewable in the method1 scope
    //  and any scopes below it, that is, any scopes created within method1
    //  and since we use an assignment operator, we assign method1.a a value, not global 'a' a value
    a = 123;
    if (true)
    {
        // this is a new scope, variables created in this block cannot be seen outside it
        //  but can see variables from above it

        System.out.println(a);  // prints 123
    }
}

ここでは、ifステートメント内のmethod1内に新しいスコープを作成します。これは、その上に表示されます。ただし、me​​thod1testのスコープはどちらも独立しているため、代入演算子を使用する場合は、aの値をローカルスコープに割り当てます。したがって、aはテスト方法の両方で異なります1

今、あなたがよりよく理解することを願っています。私は物事を伝えるのがあまり得意ではありませんが、それがスコープを理解するのに少しでも役立つなら、私はうまくいきました。さらに、それは楽しかったです。

于 2012-11-01T04:08:52.787 に答える
2

Javaは値渡しですが、ほとんどの値(プリミティブではないものすべて、この場合はint []とString)は参照です。つまり、参照渡しのように機能します。

ここに素晴らしい記事があります:http://javadude.com/articles/passbyvalue.htm

于 2012-11-01T03:10:25.710 に答える
1

arraysは特殊なタイプのオブジェクトであり、メモリはHEAPに割り当てられます。配列をパラメーターとしてメソッドに渡すと、参照値(参照のコピー)として渡されます。

これは、初期b参照とこの新しい参照が同じオブジェクトを指していることを意味します。新しい参照が別のオブジェクトを指していない限り、この参照の変更は同じオブジェクトに反映されます。そのため、元の配列に値が反映されています。

于 2012-11-01T03:08:51.590 に答える
0

すべての値が内部メソッドに渡されましたが、内部メソッドは何も返しませんでした。ただし、me​​thod2は、渡された配列の内部値を変更したため、戻り時に内部値が変更されたように見えました。

method2は、変数(パラメーター)自体に割り当てたのではなく、参照が渡されたオブジェクトの要素に割り当て唯一の方法であることに注意してください。

オブジェクトへの参照(ポインター)を変更することと、オブジェクト自体を変更することには、決定的な違いがあります。

于 2012-11-01T03:17:46.907 に答える