オブジェクトIDと関数への引数渡し
import java.util.List; import java.util.ArrayList; public class Main { public static void func(List<Integer> array) { array.set(0, 10); } public static void func2(List<Integer> array) { array = new ArrayList<Integer>(); array.add(10); array.add(2); } public static void main(String[] args) { List<Integer> p1 = new ArrayList<Integer>(); p1.add(1); p1.add(2); List<Integer> p2 = new ArrayList<Integer>(); p2.add(1); p2.add(2); func(p1); func2(p2); for (int n1: p1) System.out.print(n1 + ","); System.out.println(""); for (int n2: p2) System.out.print(n2 + ","); } } // 出力結果 // 10,2, // 1,2,
これは納得の挙動。
p2にはリスト[1, 2]への参照値が代入されていて、これがfunc2に渡される。
func2の仮引数arrayにp2に代入されていた[1, 2]への参照値がコピーされる。
新しいリストを作成し、その参照値をarrayに代入することで、arrayがp2を指さなくなる。
よって、arrayの指すリストをいくら弄ろうと、p2の指すリストは何一つ変わらない。
それでは言語を変えて。
def func(array): array[0] = 10 def func2(array): array = [10, 2] p1 = [1, 2] p2 = [1, 2] print( id(p1), id(p2), sep=', ') func(p1) func2(p2) print( p1, p2, sep= ', ' ) print( id(p1), id(p2), sep=', ') p2[1] = 20 print( id(p2), ',', sep= '', end='' ) p2 = [30, 40] print( '', id(p2) ) # 出力結果 # 140422113705928, 140422113251528 # [10, 2], [1, 2] # 140422113705928, 140422113251528 # 140422113251528, 140422113705160
p2に関してなんとも不思議な挙動をしている。
最後の行で示したように、p2[i] = n のようにリストの各要素の値を変更するだけでは、リストのidは変わらないが、
p2 = [n1, n2]のようにすると、リストのidは変わってしまう。
ということは、新しいリストを作成して、変数がその新しいリストを指すようになった、としか思えない。
だったら、func2でp2のidは変わらないとおかしくない?
PythonだけでなくRubyでも全く同じ結果で困惑している。
func2(p2)と書くところをfunc(p2)とタイプミスしてました。
正しく書くと完全に想定通りの結果でした。