0

重複の可能性:
Javaは「参照渡し」ですか?

以下に記述されている2つのJavaプログラムの違いを理解しようとしています。

 public class Swapping {

public static void main(String[] args) {

    IntWrap i = new IntWrap(10);
    IntWrap j = new IntWrap(20);

    swap(i, j);
    System.out.println("i " + i.i + ", j " + j.i);
}

public static void swap(IntWrap i , IntWrap j){

    int x = i.i;
    i.i = j.i;
    j.i = x;

    System.out.println("i " + i.i + ", j " + j.i);
}

}

public class IntWrap {

int i;
public IntWrap(int i){
    this.i = i;
}

}

出力:

i 20, j 10
i 20, j 10

そして2つ目:

public class Swapping {

public static void main(String[] args) {

    Integer i = new Integer(10);
    Integer j = new Integer(20);

    swap(i, j);
    System.out.println("i " + i + ", j " + j);
}

public static void swap(Integer i , Integer j){

    Integer temp = new Integer(i);
    i = j;
    j = temp;

    System.out.println("i " + i + ", j " + j);
}

}

出力:

i 20, j 10
i 10, j 20

Integerオブジェクトを渡しても、元のプログラムでスワップされるはずだということを理解できません。再びオブジェクトのみを渡すので、その上にラッパークラスを記述した場合、どのような違いが生じましたか。

4

4 に答える 4

4

オブジェクト参照を含むすべてのメソッド パラメータは、Java では値渡しされます。メソッド パラメータには任意の値を割り当てることができます。呼び出し元のコードの元の値は変更されません。ただし、渡されたオブジェクト自体を変更することはでき、変更はメソッドが返されたときに保持されます。

J2SE API には古い Holder クラスがあり、「戻り可能なパラメーター」 ( IntHolderStringHolderなど) を持つメソッドへの呼び出しをサポートするように特別に設計されています。IDL は in、out、inout パラメーターのサポートを必要とするため、これらは主に IDL 言語から生成されたコードで使用されます。これらのホルダーは、他のコードでは非常にまれです。

配列を使用して、参照渡しをシミュレートすることもできます。

String [] a = new String[1];  String [] b = new String[1];

void swap(String [] a, String [] b) {
   String t = a[0]; a[0] = b[0]; b[0] = t;
}
于 2013-01-14T08:21:51.717 に答える
1

Javaは値による呼び出しを使用してすべての引数を渡します。オブジェクトを関数に渡すと、オブジェクト参照(オブジェクトのアドレス)が値で渡されます。2番目のプログラムスワップでは、i=jとj=tempを割り当てます。 。したがって、i=20のアドレスj=10のアドレス(新しいオブジェクト)しかし、スワップから戻った後、メインプログラムでは、iはまだ10を指し、jは20を指します。そのため、メインプログラムで10と20が返されます。 。

しかし、最初のプログラムでは、オブジェクトのアドレスをスワップ関数に渡し、スワップ関数では、これらのアドレスが指すオブジェクトのコンテンツを変更しているため、mainメソッドに反映されています。

于 2013-01-14T08:38:34.570 に答える
1

UPS。IntegerオブジェクトはJavaでは不変です。それらの内部値を他の方法から変更することも、まったく変更することもできません。新しいIntegerオブジェクトのみを作成します。

于 2013-01-14T08:06:11.270 に答える
0

(ポインターと参照について知らない場合は、それらについて少し調べてみることをお勧めします。そうすれば、世界はより理にかなっているでしょう -ポインターの紹介)

最も簡単な説明にまとめると、Java がすべてをやり取りする方法は 2 つあります。

  • Pass-by=Value: 不変オブジェクト ( String、Integer、Double など) に使用されます。オブジェクトを再作成する場合、これらの値は 1 つの例外を除いて変更できません。

       String x = "World"; <- String x = new String("World");
       x = "Hello"; <- x = new String("Hello");
       x = x + " World"; <- x = new String("Hello" + " World");
       printOutString(x); <- printOutString("Hello World");
    

1 つの記憶場所に保持されます。変更を加えると、以前のオブジェクトとは関係のない新しいオブジェクトが作成され、別のメモリ ロケーションが参照されます。

  • 参照渡し: 不変オブジェクト ( Classes、int、double など) に使用されます。これらの値は変更することができ、メモリ内の古い場所を保持します。

      int i = 1;
      i = 2; <- value at <reference-to-memory-as-value> = 2;
      i = i + 1; <- value at <reference-to-memory-as-value> + 1;
      printOutInteger(i); <- printOutInteger(value at <reference-to-memory-as-value>);
    

このオブジェクトへの変更は、メモリの場所に対して行われます。したがって、場所は変更されません (新しいオブジェクトを作成しない限り)。

あなたのプログラムでも同じことが起こっています。メソッドで 1 つのことを言うオブジェクトは、以前の値に戻ります。あなたは、ある意味で、Operator Overloading. 送信するオブジェクションInteger(この場合)に新しい値を割り当てますが、メソッド内で値を渡しました。これは、不変であるため、メイン メソッドとは異なるメモリ位置を参照していることを意味します。したがって、メソッドが終了すると、渡されたオブジェクトは破棄され、元のメモリ位置が表示されます。Integer iIntegerInteger iInteger ij

intオブジェクトでクラスを渡すと、それらは不変ではないため、メモリの場所が (値によって) 渡され、それらの場所の値が処理されました。そのため、ここでの変更は元のオブジェクトに示されています。

これが役立つことを願っています

于 2013-01-14T09:38:18.687 に答える