今天在写代码的时候,遇到一个现象,一个数组作为参数传递到函数中,在函数中改变了这个参数的的值,结果原来的数组的值也改变了。。。
如下代码:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] datas = new int[] { 1, 2, 3, 4, 5 };
change(datas);
for (int a : datas) {
System.out.print(a + " ");
//输出结果:0 2 3 4 5
//很明显,值改变了
}
}
private static void change(int datas[]) {
datas[0] = 0;
}
}
在我的印象中,传递的参数不是一个拷贝吗?这个拷贝发生变化怎么会影响原来的值呢?于是去查找了各方资料,终于找到了答案。。。
原来:
在Java中,只有值传递,没有引用传递,而且传递的都是原来的一个拷贝,对于基础类型很好理解,传递的参数只是该基础类型的值,在被调用的方法中无论怎么改变也不会影响原来的值。但是如果传递的是一个对象实例,那么参数的值就是传递的这个对象引用的一个拷贝,既然是引用的一个拷贝,那么它和原来对象的引用指向的是一个对象,所以在被调用的函数中对象的内容是可以改变的。但是如果改变了这个对象的引用,比如重新new一下,那么它就不再指向原来的对象,这样它的改变就不会影响到原来的对象。
例如:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] datas = new int[] { 1, 2, 3, 4, 5 };
System.out.println("datas....创建时...." + datas);
change(datas);
for (int a : datas) {
System.out.print(a + " ");
//输出0 2 3 4 5
//值发生了改变
}
System.out.println("\ndatas...调用函数后..." + datas);
}
private static void change(int datas[]) {
datas[0] = 0;
System.out.println("datas...函数中..." + datas);
}
}
输出结果:
datas....创建时....[I@1a8fa0f0
datas...函数中...[I@1a8fa0f0
0 2 3 4 5
datas...调用函数后...[I@1a8fa0f0
很明显它们输出的地址都是一样的,函数中的改变影响到了原来的值,不过函数中的参数只是一个拷贝。
比如这样:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] datas = new int[] { 1, 2, 3, 4, 5 };
System.out.println("datas....创建时...."+datas);
change(datas);
for (int a : datas) {
System.out.print(a + " ");
}
System.out.println("\ndatas...调用函数后..."+datas);
}
private static void change(int datas[]) {
datas = new int[]{0,0,0};
System.out.println("datas...函数中..."+datas);
}
}
运行结果:
datas....创建时....[I@8094cc7
datas...函数中...[I@1a8fa0f0
1 2 3 4 5
datas...调用函数后...[I@8094cc7
从运行结果来看,数组在调用函数时重新创建了一个对象,其值也发生了改变,但是并没有影响到原来的对象,因为传递的参数只是一个拷贝。
然后我又这样试了一下:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s = "abcd";
System.out.println("s....创建时...." + s);
change(s);
System.out.println("s...调用函数后..." + s);
}
private static void change(String s) {
s = "aaaa";
System.out.println("s...函数中..." + s);
}
}
运行结果:
s....创建时....abcd
s...函数中...aaaa
s...调用函数后...abcd
看到这个结果有点奇怪,为什么改变s的值,原来的值没发生改变呢?
猜想应该是这样:
s = “aaaa”;其实又创建了一个对象,和原来的已经不一样了。。。
于是验证了一下。。。
public class Test {
static String s;
public static void main(String[] args) {
// TODO Auto-generated method stub
s = "abcd";
change(s);
}
private static void change(String s1) {
s1 = "aaaa";
System.out.println((s1 == s));
//输出结果:false
}
}
从运行结果看来s1和s并不相等,看来猜想是正确的。
不过为什么s1=”aaaa”重新创建了一个对象呢?什么情况下才会创建对象呢?
继续学习中。。。
注:Java中的数组是对象