我们先来看一下值传递和引用传递的定义;
值传递:在调用函数时,将实际参数复制一份传递到函数中,这样在函数中对参数进行修改,就不会影响到原来的实际参数。
引用传递:在调用函数时,将实际参数的地址直接传递到函数中。这样在函数中对参数进行的修改,就会影响到实际参数。
实参与形参
形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。
实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为
我们先举个简单的例子: i的值就是实际参数,j就是形式参数
package method;
public class Demo02 {
public static void main(String[] args) {
Demo02 demo = new Demo02();
int i = 10;
demo.test(i);
System.out.println("i: "+i);
}
public void test(int j){
j = 20;
System.out.println("j: "+j);
}
}
运行结果为,可以发现原来的i值并没有发生改变。
第二个例子:
public class Demo02 {
public static void main(String[] args) {
Demo02 demo = new Demo02();
User user1 = new User();
user1.setName("A1")
demo.test(user1);
System.out.println("main--->"+user1.getName()); //B1
}
public void test(User user){
user.setName("B1");
System.out.println("Test-->" +user.getName());//B1
}
}
发现两个都是输出B1,这是有人可能会这样认为:Java的方法中,在传递普通类型的时候是值传递,在传递对象类型的时候是引用传递,但是这种说法也是错误的。我们接着看下一个例子
package method;
public class Demo02 {
public static void main(String[] args) {
Demo02 demo = new Demo02();
User user1 = new User();
user1.setName("A1")
demo.test(user1);
System.out.println("main--->"+user1.getName()); //A1
}
public void test(User user){
User user = new User();
user.setName("B1");
System.out.println("Test-->" +user.getName());//B1
}
}
如图可以看到,当new了一个对象时,会在内存中开辟一片空间保存name的数据,user1存有该内存的地址0x123456,当user1作为实际参数传递给形式参数user时,会把地址传递给user。
如果如例2一样,没有新new一个对象的话,会将user1的值赋给user,那么user和user1是指向同一个地址的,所以不论是user的修改还是user1的修改,本质上都是对0x123456地址上保存的数据进行修改。
但是要是如例3一样,重新new了一个对象,重新开辟了一片内存赋值给user,那么user和user1指向的是不同地址,对user的修改不会影响到user1指向内存的数据。
所以当传递的参数是对象数据类型时,对象本身指向的是它在内存中的地址,所以传递的应该是对副本,所以在调用方法时,如果没有重新new一个对象的话,方法内的对象地址指向和传递进来的对象地址是保持一致的,所以地址指向不变,那么对其值进行修改时,值也会发生改变。
总之,Java都是值传递的。