事实上,Java 是按值传递的。但它也有“引用数组”!这就是为什么许多人认为 Java 对对象(至少对数组)是按引用传递,而对基元来说只是按值传递。
这是一个简短的测试:
String[] array = new String[10];
array[0] = "111";
ArrayList one = new ArrayList();
one.add(array);
ArrayList two = (ArrayList) one.clone(); //Alternate with: ArrayList two = one;
String[] stringarray1 = (String[]) one.get(0);
String[] stringarray2 = (String[]) two.get(0);
System.out.println("Array: "+one+" with value: "+stringarray1[0]);
System.out.println("Array: "+one+" with value: "+stringarray2[0]);
array[0] = "999";
String[] stringarray3 = (String[]) one.get(0);
String[] stringarray4 = (String[]) two.get(0);
System.out.println("Array: "+one+" with value: "+stringarray3[0]);
System.out.println("Array: "+two+" with value: "+stringarray4[0]);
无论你是克隆还是使用 =,System.out.print 都会是这样的:
Array: [[Ljava.lang.String;@addbf1] with value: 111
Array: [[Ljava.lang.String;@addbf1] with value: 111
Array: [[Ljava.lang.String;@addbf1] with value: 999
Array: [[Ljava.lang.String;@addbf1] with value: 999
这证明了克隆和数组是有害的组合,因为数组只存储指针!我仍然需要测试这是否也适用于无数组对象......因为这意味着 Java 总是“按引用存储”(并且“克隆”功能对于任何对象来说都只是一个糟糕的笑话包含数组),而只有基元是真实值,没有引用!
因为我们知道逻辑:storage-by-reference x pass-by-value == "storage by value x pass-by-reference"(对于对象!),
虽然我们从学校开始就已经知道:按值存储 x 按值传递(对于基元)
那么,我们是否都被我们的编程老师欺骗了(即使是在大学里)?也许吧,但他们至少没有犯任何逻辑错误……所以这不是谎言,只是错了。
编辑
我用一个类写了和上面一样的代码,首先是数据结构:
public class Foobar implements Cloneable {
String[] array;
public Foobar() {
this.array = new String[10];
}
public String getValue(){
return array[0];
}
public String[] getArray(){
return array;
}
public void setArray(String[] array){
this.array = array;
}
@Override
public Object clone(){
try{
Foobar foobar = (Foobar) super.clone();
foobar.setArray(array);
return foobar;
}
catch(Exception e){
return null;
}
}
}
现在是控制器:
String[] array = new String[10];
array[0] = "111";
Foobar foo1 = new Foobar();
foo1.setArray(array);
Foobar foo2 = foo1; //Alternation: Foobar foo2 = (Foobar) foo1.clone();
System.out.println("Instance: "+foo1.getArray()+" with value: "+foo1.getValue());
System.out.println("Instance: "+foo2.getArray()+" with value: "+foo2.getValue());
array[0] = "999";
System.out.println("Instance: "+foo1.getArray()+" with value: "+foo1.getValue());
System.out.println("Instance: "+foo2.getArray()+" with value: "+foo2.getValue());
测试结果总是这样——无论我使用 = 还是 clone():
Instance: [Ljava.lang.String;@42e816 with value: 111
Instance: [Ljava.lang.String;@42e816 with value: 111
Instance: [Ljava.lang.String;@42e816 with value: 999
Instance: [Ljava.lang.String;@42e816 with value: 999
现在我的口袋里有了“主阵列”,我可以立即统治所有物体! (这真的不是一件好事)
我一直对 Java 数组感到不安,但我说不出它是什么。现在我知道了,我感觉很好,因为从那以后我只使用数组作为对象的容器......只是发现自己非常惊讶它们在 PHP 等脚本语言中的重要性!
不过,Java 数组非常适合线程之间的同步,因为您可以轻松地传递它们并且仍然可以访问共享值。但是来自 PHP 或 C++ 或其他地方的程序员可能确实会遇到 Java 数组的一些问题。 ;D
哦,我喜欢这篇文章:http://javadude.com/articles/passbyvalue.htm
更新:我找到了一个很好的解决方案来复制任何包含数组的对象,请在此处查看我的评论:Bug in using Object.clone()