事实上,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 始终是“按引用存储”(并且“克隆”功能对于任何对象来说都只是一个糟糕的笑话包含数组),而只有原语是真实值,没有引用!
并且由于我们了解逻辑:按引用存储 x 按值传递 ==“按值存储 x 按引用传递”(对于对象!),
虽然我们从学校开始就已经知道:按值存储 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
更新:我找到了一个很好的解决方案来复制任何包含数组的对象,请在此处查看我的评论:使用 Object.clone() 中的错误