> 文章列表 > Java 之 值传递 引用传递

Java 之 值传递 引用传递

Java 之 值传递 引用传递

概念

  • 值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

  • 引用传递:指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

误区

  1. 通过传递的内容来区分,如果是个值,就是值传递;如果是个引用,就是引用传递。
  2. java 是 引用传递。
  3. 传递的参数如果是普通类型,就是值传递;如果是对象就是引用传递。

举个例子

例子1

public class Test {public static void main(String[] args) {int num1 = 10;int num2 = 20;temp(num1, num2);System.out.println("main() num1 = " + num1);System.out.println("main() num2 = " + num2);}public static void temp(int a, int b) {int temp = a;a = b;b = temp;System.out.println("temp() a = " + a);System.out.println("temp() b = " + b);}
}## 输出结果为:temp() a = 20temp() b = 10main() num1 = 10main() num2 = 20

为什么temp方法输出的值进行了交换,而main输出的却没交换?

1.对于基本数据类型来说,使用的是值传递。即 temp=a;a=b;b=temp; 这种情况。
2.但在函数方法中,即实参传递给形参这种情况下,首先把实参复制了一份,并复制给形参。也就是得到的形参是实参的备份。
3.通过对复制出来的备份进行值的交换,并不会影响原来的数值。这也就说明了为什么temp方法输出的值进行了交换,而main输出的却没交换

例子2

public class Test {public static void main(String[] args) {Student t1 = new Student("张三", 18);Student t2 = new Student("李四", 19);temp(t1, t2);System.out.println("main() t1:" + t1);System.out.println("main() t2:" + t2);}private static void temp(Student t1, Student t2) {Student t = t1;t1 = t2;t2 = t;System.out.println("temp() t1:" + t1);System.out.println("temp() t2:" + t2);}
}
class Student {String name;int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Test {" +"name='" + name + '\\'' +", age=" + age +'}';}
}
## 输出结果为:temp() t1:Test {name='李四', age=19}temp() t2:Test {name='张三', age=18}main() t1:Test {name='张三', age=18}main() t2:Test {name='李四', age=19}

原因同例子1,本例子是将实参的地址复制了一份,并赋值给形参,然后进行交换,使其改变指向。
但是,注意: 这并不是引用传递,在Java里只能叫传递了对象的引用,本质上是传递了对象的引用(地址)的副本,这也算值传递。

若将交换函数改成如下代码,则成功进行交换

public class Test {public static void main(String[] args) {Student t1 = new Student("张三", 18);Student t2 = new Student("李四", 19);change(t1,t2);System.out.println("main() t1:" + t1);System.out.println("main() t2:" + t2);}private static void change(Student t1, Student t2) {Student t = new Student("王五",20);t.name=t1.name;t.age = t1.age;t1.name= t2.name;t1.age= t2.age;t2.name= t.name;t2.age = t.age;System.out.println("change() t1:" + t1);System.out.println("change() t2:" + t2);}private static void temp(Student t1, Student t2) {Student t = t1;t1 = t2;t2 = t;System.out.println("temp() t1:" + t1);System.out.println("temp() t2:" + t2);}
}
class Student {String name;int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Test {" +"name='" + name + '\\'' +", age=" + age +'}';}
}
## 输出结果为:change() t1:Test {name='李四', age=19}change() t2:Test {name='张三', age=18}main() t1:Test {name='李四', age=19}main() t2:Test {name='张三', age=18}

总结

  • 值传递是指在调用函数时将实际参数复制一份传递到函数中;引用传递是指在调用函数时将实际参数的引用直接传递到函数中。

  • Java中的基本数据类型是值传递。针对 八种基本数据类型来讲,当以参数形式传递给方法是,会把值copy一个新的变量,供该方法内使用。两个变量互不影响

  • 对于八种基本数据类型的包装类和String 他们是不可变对象 ,所以也会以值传递的形式传进方法内。比如:Integer 类中 有final修饰

  • 很多人却误认为Java中的对象传递是引用传递。之所以会有这个误区,主要是因为Java中的变量和对象之间是有引用关系的。Java语言中是通过对象的引用来操纵对象的。所以,很多人会认为对象的传递是引用的传递。

  • Java对象的传递,是通过复制的方式把引用关系传递了,如果我们没有改引用关系,而是找到引用的地址,把里面的内容改了,是会对调用方有影响的,因为大家指向的是同一个共享对象。

  • 引用传递:对于引用数据类型,会把对象的引用传入方法内,会相互影响.

  • 引用传参,传的是对象的地址,通过地址访问地址指向的内存空间