首先,我们要明确一点,Java中只有值传递,至于原因,下面说。
错误理解:
- 参数是值,就是值传递;参数是引用,就是引用传递。
- 参数是基本类型,就是值传递;参数是对象类型(引用类型),就是引用传递。
在说值传递和引用传递之前,我们来说一下形参和实参:
- 形参:定义函数时所使用的参数,用来接收调用函数时传入的参数
-
实参:调用参数时实际传入的参数
图片.png
public class Test {
public static void main(String[] args) {
//123是实参
print("123");
}
//str是形参
public static void print(String str) {
System.out.println(str);
}
}
接下来,来看一下什么是值传递和引用传递,
- 值传递:值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
- 引用传递:引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
好了,上代码:
public class Test {
public static void main(String[] args) {
int i=0;
print(i);
System.out.println(i);
}
public static void print(int i) {
i++;
}
}
图片.png
i的值没有改变,说明是值传递
再来看一下引用类型的参数:
public class Test {
public static void main(String[] args) {
A a = new A();
a.setName("a");
print(a);
System.out.println(a.name);
}
public static void print(A a) {
a.setName("b");
}
}
class A {
String name;
void setName(String name) {
this.name = name;
}
}
图片.png
这是为啥呢?参数怎么变了,好,我们再看一个程序:
/*
* Copyright (c) 2018 lyc All Rights Reserved.
*
*
*
*
*
*
*/
/**
* description .
*
* @author liyaocai
* @version V1.0
* @date 2018/7/18 12:56
* @since 1.8
*/
public class Test {
public static void main(String[] args) {
A a = new A();
a.setName("a");
print(a);
System.out.println(a.name);
}
public static void print(A par) {
par = new A();
par.setName("b");
}
}
class A {
String name;
void setName(String name) {
this.name = name;
}
}
图片.png
这里为啥又没变化呢?我们来看一张图
图片.png
我们创建了一个对象a,这时候在堆里开辟了一块空间存放他,好了我们记住他的内存地址0X123,当调用print,把a作为实参传给par,会把这个地址交给par,执行 par = new A();的时候,par指向了0x456,如果是引用传递,那么a也应该指向0x456,然而并没有,所以,上面的参数其实是值传递,把实参对象引用的地址当做值传递给了形式参数。在第二个例子中,并没有对形参本身进行修改,而是修改的形参持有的地址中存储的内容
最后一个坑就是String,String=“***”,没有new,实际上也会改变指向(String是不可变的)
最后总结一下:Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用
网友评论