2

次のケースを考えてみましょう。

    List<Integer> listOne = new ArrayList<>();
    List<Integer> listTwo = new ArrayList<>();
    listOne.add(1);I think this happens due to 
    listOne.add(2);
    listOne.add(3);
    Collections.reverse(listOne);
    listTwo = listOne;  //listTwo has same reference 
    Collections.reverse(listOne);
    System.out.println(listOne);  //out put [1, 2, 3] 
    System.out.println(listTwo);  // same out put

Java is pass by value, where values (for non primitive types) happen to be references.これにより、この種のシナリオで Java が生き残ることができると思います。正直に言うと、なぜjavaを避けよpass by referenceうとし、違うものになろうとするのsome of other languagesでしょうか? Javaはまだ参照渡しの動作に苦しんでいますか?

編集:さらに、上記のコードで何が起こるかを説明してください

4

4 に答える 4

3

Java は、参照渡しの動作に悩まされることはありません。それを楽しんでいます :)

あなたが書くとき

リスト listOne = new ArrayList<>();

次の 3 つの点を考慮する必要があります。

1) メモリのチャンクであり、listOneという名前の変数

2) ArrayList のインスタンスであるヒープ上のオブジェクト。これはメモリのより大きなチャンクであり、名前はありません。

3) listOne 変数の値。メモリ チャンクではありませんが、変数 listOne のメモリに配置された 0 と 1 のセットであり、その値にも名前はありません。

listOne が値または参照によって渡される場合、誤解を招く不正確な専門用語を使用します。listOne (thing 1) は、値渡しでも参照渡しでも、まったく渡されません。listOne の値 (3) が渡され、これにより ArrayList オブジェクト (2) にアクセスできるようになります。したがって、「listOne」という名前を使用しているが、3 を意味する場合は値によって渡され、2 を意味する場合は参照によって渡されます。どちらの場合も、"listOne" という名前は、モノ 2 またはモノ 3 の正しい名前ではありませんが、短くて便利なので使用されます。

于 2013-08-15T09:52:46.533 に答える
1

Java は値渡しです。実引数のコピーがパラメーターに渡されます。仮パラメーターの変更が実引数に表示されないプリミティブ データ型の場合は明らかです。

 static void incre(int a)
      {
        a++;
      }
public static void main (String a[])
{ 
  int c=3;
  incre(c);
  System.out.println(c);  //still prints 3
}

参照の場合は正確に起こりますが、参照のコピーを作成しても新しいオブジェクトは作成されず、両方が同じオブジェクトを指すようになりました。したがって、参照による変更はここに反映されます。

class Demo { 
  int c =2; 

  Demo(int c)
    {
       this.c=c;
    } 

  void incObject (Demo x)    
    {
       (x.c)++;
    }

  int show()
   {
      return c;
   }
  public static void main (String []args)    
   {
    Demo o = new Demo(1);
    o.incObject(o);
   System.out.print(o.show()); //prints 2

 }

}
于 2013-08-15T10:03:45.270 に答える
0
 Collections.reverse();

バッキング配列を変更します。これは実装から明らかです。

 public static void reverse(List<?> list) {
        int size = list.size();
        if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
            for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
                swap(list, i, j);
        } else {
            ListIterator fwd = list.listIterator();
            ListIterator rev = list.listIterator(size);
            for (int i=0, mid=list.size()>>1; i<mid; i++) {
                Object tmp = fwd.next();
                fwd.set(rev.previous());
                rev.set(tmp);
            }
        }
    }

これでlistOnelistTwo同じバッキング配列を指す同じ参照ができました。したがって、どちらのハンドル(listOne または listTwo) がバッキング配列を変更しても、もう一方は同じ変更を反映します。あなたの場合:

    Collections.reverse(listOne);  // backing array has [3,2,1]
    listTwo = listOne;  //listTwo has same reference 
    Collections.reverse(listOne);  // backing array has [1,2,3]
    System.out.println(listOne);  //out put [1, 2, 3] 
    System.out.println(listTwo);  // same out put

値/参照による受け渡しに関する限り。あなたはそれを自分で言いました:

Java は値渡しであり、値はたまたま参照されます。

Java が参照渡しを避けて、他の言語とは異なるものにしようとするのはなぜですか?

主な理由の 1 つは、Java(JVM) が独自のメモリを管理することです。

于 2013-08-15T09:26:57.580 に答える
-2

Collections.reverse(listOne);listOne(オブジェクト)への参照を値渡しします。これは、「参照渡し」を定義する方法です。プリミティブ以外はすべてこの方法で渡されます: 参照渡しです。それを回避しようとはしません。ポインタを明示的に使用しないという点で C++ と異なるだけです。

編集: わかりました、あなたがどこから来ているかわかりました。

private static void changelist(List<Integer> list) {
    list.add(4);//This modifies the list object
    list = new ArrayList<Integer>();//This modifies the local copy of the reference to the list object
    list.add(5);
}
public static void main(String[] args) {
    List<Integer> list = new ArrayList<Integer>();
    list.add(1);
    list.add(2);
    list.add(3);
    System.out.println(list);//output is [1,2,3]
    //This copies the value of the reference. 
    //If you modify the object in the underlying 
    //function, changes will be preserved when you return
    //However if you modify what the reference points to,
    //the function will only modify the local copy
    changelist(list);
    System.out.println(list);//output is [1,2,3,4]

}
于 2013-08-15T09:22:04.787 に答える