在使用面对对象语言的编程中(目前已测java,c#),要注意复制对象或者数组时可能引起不必要的错误。
其实这点在书中提到多次,不过直到最近编程吃了大亏,调试了很久才发现问题所在,才由此重视这个问题。
叙述如下:
在给对象赋值时如果我们使用下列语句
Object a = b;
那么在以后编程的过程中很容易出现令人疏忽的bug,即当改动a时b的值也相应的改变,而我们不需要b的相应改变。
因此,复制对象的值到另外一个对象时,无论我们希望是否会改变原对象,我们一般都采用浅复制的方法,即
Object a = b.clone();
如果某个对象没有实现clone方法,那么我们只好自己实现clone的操作,譬如复制java中的Map和C#中的Dictionary,
都需要我们自己对新map或者dictionary一一赋值,特别注意下例:
Dictionary<int,int []> a = ...;
Dictionary<int,int []> b = new Dictionary<int,int []>();
foreach(int key in a.keys)
{
b.add(key,a[key]);
}
这里标红色字体将会报错,因为给b复制将b的value值和a的value值绑在一起,都指向同一个引用,即只要改动b[key],
a[key]也会相应的改动,正确的做法是b.add(key,(int []) a[key].clone());
java示例
Map<Integer, int[]> testMap = new HashMap<Integer,int[]>();
testMap.put(0, new int []{1,2});
testMap.put(1, new int []{2,3});
Map<Integer,int []> changeMap = testMap;
int[] changeIntArray = testMap.get(1);
int changInt = testMap.get(1)[1];
changeMap.put(0, new int []{2,3});
System. out.println(testMap.get(0)[0]);
changeIntArray[0] = 5;
changeIntArray[1] = 6;
System. out.println(testMap.get(1)[0]);
changInt = 9;
System. out.println(testMap.get(1)[1]);
以上代码输出结果将会为:2,5,6。
但是如果我们给changeIntArray赋值令其指向新数组,即changeIntArray=new int[]{1,2};
将不会影响原来的testMap的值,因为此时changeIntArray的引用指向了新的一个int数组{1,2},不再指向原来的数组引用。(具体的还不是太明白,求指教。。。)
唉,终于发现果然 纸上得来终觉浅,绝知此事要躬行 。。。书上提到的东西还是要认真对待啊。。。