之前在代码中刚好遇到过同样的问题, 现在我自己举个例子来大概描叙一下情况:
上诉例子中, 代码的意图是想着把list1 和 list2交换一下, 看代码运行结果:
[img]http://dl2.iteye.com/upload/attachment/0122/2377/82f26fe8-441e-3482-9007-dbcb90fe5513.png[/img]
为了进行分析, 我直接在swap()方法体中加了输出语句.
可以看出, 结果是list1 和 list2的引用并没有发生交换.
在我以前的知识中, 会讲到各种作用域阿, 局部参数等的问题, 其实对于当初新手的我来说要记住这些东西是很麻烦的....在我接触到 值传递和引用传递这两个概念以及了解到java语言中是值传递的, 我就瞬间明白了上述运行结果中没有发生交换的原因.
值传递概念:表示方法接收的是调用者提供的值.得到的是参数值的一个拷贝.(这里概念来自于Core Java 卷一 第九版 方法参数这章)
首先, 用基本数据类型来解释下这个 值传递的概念:
运行结果:
[img]http://dl2.iteye.com/upload/attachment/0122/2379/7f3e1ecc-cf9a-37ab-b017-56a1841db2ae.png[/img]
运行结果是:x没有被改变值, 然后我在add()方法最后面增加x的输出:
[img]http://dl2.iteye.com/upload/attachment/0122/2381/ff0b2240-07eb-3a51-a149-e0ccae4cbfdc.png[/img]
用图例分析:
[img]http://dl2.iteye.com/upload/attachment/0122/2385/aa059762-1a13-3cc8-ace1-06d396bfcf85.png[/img]
其实在add()方法里面, 我们操作的是参数x的值的一个拷贝(注意这里是值的拷贝),即copy of x, 在方法里面操作的都是copy of x, 所以并不影响原来x的值.
[b]对于引用类型参数的传递, 的引用的拷贝.下面用图例分析开头的代码:[/b]
[img]http://dl2.iteye.com/upload/attachment/0122/2387/3e7067a4-8ce3-32de-8df9-28f686b05f8a.jpg[/img]
先说明下:如果对栈, 堆, 指针有些了解, 那么理解起来就很容易
从图例来看, swap()方法里面获取得其实是来自于list1和list2的拷贝, 拷贝的是list1(0x00)内存块里面的值(0x10), 并不是把(0x00)传过去(其实这种就是引用传递).list2和l2也是同理
因此当l1 和 l2互换的时候, 换的是0x02 和 0x03内存块里面的内容, 所以在swap()方法里面是, l1 和 l2 是已经发生交换了, 但是外部的list1 和 list2 并没有发生任何影响.
这里额外提一点, 假设swap()方法如下:
那么外部的list1 和 list2肯定各自增加了"a", "b", 因为这里的l1 和 list1 指向的实例都是一样的.即l1 和 list1 对应的内存块里面存的值都是0x10. l2 和 list2也是同理.
如果不明白的话可以手动敲一下代码, 然后画图理解, 最重要的是稍微理解堆, 栈, 和java中关于指针的知识就行啦.
若有不对的地方, 请指正~thx
import java.util.*;
public class StringTest {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
list1.add("1");
ArrayList list2 = new ArrayList();
list2.add("2");
System.out.println("list1:" + list1.get(0));
System.out.println("list2:" + list2.get(0));
System.out.println("----------------");
swap(list1, list2);
System.out.println("After invoking swap()");
System.out.println("list1:" + list1.get(0));
System.out.println("list2:" + list2.get(0));
}
static void swap(List l1, List l2) {
List temp = l1;
l1 = l2;
l2 = temp;
System.out.println("------swap() begin-----");
System.out.println("l1:" + l1.get(0));
System.out.println("l2:" + l2.get(0));
System.out.println("------swap() end-----");
}
}
上诉例子中, 代码的意图是想着把list1 和 list2交换一下, 看代码运行结果:
[img]http://dl2.iteye.com/upload/attachment/0122/2377/82f26fe8-441e-3482-9007-dbcb90fe5513.png[/img]
为了进行分析, 我直接在swap()方法体中加了输出语句.
可以看出, 结果是list1 和 list2的引用并没有发生交换.
在我以前的知识中, 会讲到各种作用域阿, 局部参数等的问题, 其实对于当初新手的我来说要记住这些东西是很麻烦的....在我接触到 值传递和引用传递这两个概念以及了解到java语言中是值传递的, 我就瞬间明白了上述运行结果中没有发生交换的原因.
值传递概念:表示方法接收的是调用者提供的值.得到的是参数值的一个拷贝.(这里概念来自于Core Java 卷一 第九版 方法参数这章)
首先, 用基本数据类型来解释下这个 值传递的概念:
public class CopyTest {
public static void main(String[] args) {
int x = 10;
System.out.println(x);
add(x);
System.out.println("After add()");
System.out.println(x);
}
static void add(int x) {
x += 10;
}
}
运行结果:
[img]http://dl2.iteye.com/upload/attachment/0122/2379/7f3e1ecc-cf9a-37ab-b017-56a1841db2ae.png[/img]
运行结果是:x没有被改变值, 然后我在add()方法最后面增加x的输出:
[img]http://dl2.iteye.com/upload/attachment/0122/2381/ff0b2240-07eb-3a51-a149-e0ccae4cbfdc.png[/img]
用图例分析:
[img]http://dl2.iteye.com/upload/attachment/0122/2385/aa059762-1a13-3cc8-ace1-06d396bfcf85.png[/img]
其实在add()方法里面, 我们操作的是参数x的值的一个拷贝(注意这里是值的拷贝),即copy of x, 在方法里面操作的都是copy of x, 所以并不影响原来x的值.
[b]对于引用类型参数的传递, 的引用的拷贝.下面用图例分析开头的代码:[/b]
[img]http://dl2.iteye.com/upload/attachment/0122/2387/3e7067a4-8ce3-32de-8df9-28f686b05f8a.jpg[/img]
先说明下:如果对栈, 堆, 指针有些了解, 那么理解起来就很容易
从图例来看, swap()方法里面获取得其实是来自于list1和list2的拷贝, 拷贝的是list1(0x00)内存块里面的值(0x10), 并不是把(0x00)传过去(其实这种就是引用传递).list2和l2也是同理
因此当l1 和 l2互换的时候, 换的是0x02 和 0x03内存块里面的内容, 所以在swap()方法里面是, l1 和 l2 是已经发生交换了, 但是外部的list1 和 list2 并没有发生任何影响.
这里额外提一点, 假设swap()方法如下:
static void (List l1, List l2) {
l1.add("a");
l2.add("b");
}
那么外部的list1 和 list2肯定各自增加了"a", "b", 因为这里的l1 和 list1 指向的实例都是一样的.即l1 和 list1 对应的内存块里面存的值都是0x10. l2 和 list2也是同理.
如果不明白的话可以手动敲一下代码, 然后画图理解, 最重要的是稍微理解堆, 栈, 和java中关于指针的知识就行啦.
若有不对的地方, 请指正~thx