前段时间写java代码遇到一个值传递和引用传递的问题,回去查了下相关资料,对Java参数传递问题有了新的理解和认识,但是有个问题还是很困惑,那就是Java里到底是不是只有值传递,因为查阅资料的过程中,看到很多大牛说Java只有值传递,引用传递其实传递的是地址值,本身来说也是一种值传递,但是也有人说既有值传递,又有引用传递,姑且不去争论这个究竟,只是站在不同角度看待同一个问题所以得出了两个不同的观点,其实两个说法的原理是一样的,只要搞清楚Java参数传递的机制,叫什么传递也无所谓了,接下来跟大家分享一下我的一些粗浅的心得:
1.什么是值传递
传递实参的一个副本给形参,在被调用函数内对形参的修改不会影响到原来的实参。
public class Test {
public static void main(String[] args) {
int a=1;
Test.changeNum(a);
System.out.println("Main方法中的a = "+a);
}
public static void changeNum(int a){
//do something
a+=1;
System.out.println("changeNum方法中的a = "+a);
}
}
运行结果是:
changeNum方法中的a = 2
Main方法中的a = 1
可见实际参数的值并没有发生改变,改变的只是作为副本的形参。
值传递重要特点:传递的是值的拷贝,传递后就没有任何联系了。
2.什么是引用传递
本质上还是值传递,只是把引用的值复制一份传递给形参,指向实参引用所指向的值,当对形参指向的内容操作时,就相当于对实参本身就行的操作。
public class Test1 {
public static void main(String[] args) {
A a = new A();
a.age=10;
test1(a);
System.out.println("Main方法里age = "+a.age);
}
public static void test1(A a){
a.age=20;
System.out.println("test1方法里age = "+a.age);
}
}
class A{
int age=0;
}
运行结果如下:
test1方法里age = 20
Main方法里age = 20
3. 引用传递的过程-内存分配示意图
要想正确的理解java的引用传递,就必须了解java内存分配的过程,下面的内存分配示意图可以帮助我们理解这个过程:
(1)运行开始,到第4行,Main方法里创建了一个类A的实例,内存分配示意图如下:
main方法里的变量age→这是类A的一个实例a,此时age=0.
(2)运行到5行,是修改A实例里age的值,运行后内存分配示意图如下:
main方法里的变量age→这是类A的一个实例a,此时age=10.
(3)运行到6行,是把main方法中的变量a所指向的内存空间地址,按引用传递给test1方法中的a变量。*注意:这两个变量a是完全不同的,不要被名称相同所蒙蔽。内存分配示意图如下:
由于是按引用传递,也就是传递的是内存空间的地址,所以传递完成后形成的新的内存示意图:
(4)运行到10行,为test1方法里的变量a指向的A实例的age进行赋值,然后形成新的内存示意图:
此时A实例的age值的改变是由test1方法的形参改变引起的。
(5)运行到11行,输出test1方法里的age=20.
(6)运行到第7行,输出Main方法里的age=20.
4. 再次理解引用传递
将上述代码稍作修改:
public class Test1 {
public static void main(String[] args) {
A a = new A();
a.age=10;
test1(a);
System.out.println("Main方法里age = "+a.age);
}
public static void test1(A a){
//此处增加了一行,将形式参数指向了一个新的A的实例
a=new A();
a.age=20;
System.out.println("test1方法里age = "+a.age);
}
}
class A{
int age=0;
}
运行结果:
里age = 20
Main方法里age = 10
其实也不难理解,前面3部和上述相同,第4步开始如下:
(4)运行到11行,作为形参的a变量指向了新的A的实例。
(5)运行到12行,形参a变量的age重新赋值
此时修改的是test1方法变量a的age,与main方法中的变量a所指的地址不同,所以main方法中的变量a的age值没有发生改变。
(6)运行到13行,输出test1方法里的age =20.
(7)运行到7行,输出Main方法里的age=10.
5.引用传递String类型的探讨
我们都知道java里的String类型是一种引用类型,而不是值类型,虽然很多地方和值类型的特征相似,看下面这个例子:
public class Test {
public static void main(String[] args) {
String str="Hello";
Test.changeStr(str);
System.out.println("Main方法中的str = "+str);
}
public static void changeStr(String str){
//do something
str+=" World!";
System.out.println("changeStr方法中的str = "+str);
}
}
输出结果:
changeStr方法中的str = Hello World!
Main方法中的str = Hello
那么为什么String类型的引用传递没有改变Main方法里的str的值呢?大家可以去深入了解下java里String类型的特性,答案就显而易见,这里就不做赘述了。以上是我的一点浅薄的见解,希望大家多多指教。