Java数据类型中分为基本数据类型(8个)和引用数据类型(类,接口,数组),基本数据类型都是在栈上申请的,引用数据类型是在栈上申请引用,堆上申请实体的,所以可以认为栈上存放的是堆上实体的地址。
有不少人对java中函数参数传递的过程有迷惑,其实用一句话来说就是“函数的参数传递的都是实参的副本”,这点和C语言是一样的,只不过具体用起来在不同的情况下就有不同的效果了。接下来分三种情况讨论,都用常见的swap这个例子分析。
1,传入的是基本的数据类型:
1 public static void main(String[] args){
2 int x =100,y=200;
3 SOP.sop(x+"----"+y);
4 swap1(x, y);
5 SOP.sop(x+"----"+y);
6
7 }
8
9 static void swap1(int a ,int b){
10 int i = a;
11 a = b;
12 b = i;
13 }
这里对传入的参数进行了互换的操作,但是因为传入的是实际参数的副本,所以并没有对原来的参数有影响,因此是达不到互换的效果的。
2,传入的是引用类型,在函数内修改了值本身。
1 public static void main(String[] args){
2 String x = new String("100");
3 String y = new String("200");
4 SOP.sop(x+"----"+y);
5 swap1(x, y);
6 SOP.sop(x+"----"+y);
7
8
9 }
10
11 static void swap1(String a ,String b){
12 a = a.replace('1','2');
13 b = b.replace('2','1');
14
15 }
这里很多人很可能会弄错,认为会实现互换了,但是按照刚才的那个规则分析的话:传入的是引用的副本,而这里正好有个string的陷阱,那就是string本身是不会改变的,对string进行替换操作后,其实是返回了一个新的string,然后swap函数中的引用指向了那个返回来的新的string,也是引用改变了引用的对象(注意:是引用的对象改变了,而不是引用对象的值改变了)。
3,传入的是引用类型,在函数内修改了指向对象的值。
1 public static void main(String[] args){
2 StringBuffer x = new StringBuffer("100");
3 StringBuffer y = new StringBuffer("200");
4 SOP.sop(x+"----"+y);
5 swap1(x, y);
6 SOP.sop(x+"----"+y);
7
8
9 }
10
11 static void swap1(StringBuffer a ,StringBuffer b){
12 a.replace(0, 1, "2");
13 b.replace(0, 1, "1");
14
15 }
同样,这个例子中,传入形参的是实参的副本,但是由于stringbuffer的特性是:操作后返回的是本身,而不是一个新的对象,因此,这里可以认为是改变了引用的对象的值。所以既然副本和实参都是指向同一个对象,副本指向的值改变了,那么实参指向的值当然改变了。