值传递和引用传递

在java中实质只存在一种传递方式:即值传递。 而引用传递是对C/C++而言的。结论:

  对于基本类型,在方法体内对方法参数进行重新赋值,并不会改变原有变量的值。

  对于引用类型,在方法体内对方法参数进行重新赋予引用,并不会改变原有变量所持有的引用。

  方法体内对参数进行运算,不影响原有变量的值。

  方法体内对参数所指向对象的属性进行运算,将改变原有变量所指向对象的属性值。

  在JAVA中变量有以下两种:

  基本类型变量,包括char、byte、short、int、long、float、double、boolean。

  引用类型变量,包括类、接口、数组(基本类型数组和对象数组)。

  最后我们得出如下的结论:

  基本类型和基本类型变量被当作参数传递给方法时,是值传递。在方法实体中,无法给原变量重新赋值,也无法改变它的值。

  对象和引用型变量被当作参数传递给方法时,在方法实体中,无法给原变量重新赋值,但是可以改变它所指向对象的属性。

  2 public class Person

  3 {

  4 private String name = null;

  5 private int age = 0;

  6

  7 public Person(String name, int age) {

  8 this.name = name;

  9 this.age = age;

  10 }

  11

  12 public void changeName(String newName) {

  13 this.name = newName;

  14 }

  15

  16 public void changeAge(int newAge) {

  17 this.age = newAge;

  18 }

  19

  20 public String toString() {

  21 return "Person - Name: " + name + ", Age: " + age;

  22 }

  23 }

  24

  25 public class PassByValue

  26 {

  27 public static void main(String[] args) {

  28 // one example

  29 String value1 = "value1: aaa";

  30 String value2 = "value2: bbb";

  31

  32 swapValue(value1, value2);

  33

  34 System.out.println(value1);

  35 System.out.println(value2);

  36

37 // another example

  38 Person person = new Person("张三", 20);

  39

  40 System.out.println(person.toString());

  41

  42 changePerson(person);

  43

  44 System.out.println(person.toString());

  45 }

  46

  47 public static void swapValue(String tmpValue1, String tmpValue2) {

  48 String tempStr = tmpValue1;

  49 tmpValue1 = tmpValue2;

  50 tmpValue2 = tempStr;

  51 }

  52

  53 public static void changePerson(Person tmpPerson) {

  54 tmpPerson.changeName("李四");

  55 tmpPerson.changeAge(30);

  56 }

  57 }

  58

  考虑一下上面这段代码的输出结果是什么?

  我相信绝大多数人都能快速的给出正确答案:

  value1: aaa

  value2: bbb

  Person - Name: 张三, Age: 20

  Person - Name: 李四, Age: 30

  答案为什么是这样的呢?那么 Java 到底是按值传递还是按引用传递参数的呢?

  例 子1中的 swapValue() 方法不起作用,看起来是按值传递参数的,例子2中的 changeName() 和 changeAge() 方法起作用,从表面上看起来好像又是按引用传递参数的。呵呵,别急,先让我们来弄清楚一个重要的概念,就是 Java 操纵对象都是通过引用来实现的,所有的对象变量都是所指向的对象的引用,那也就是说所有对象变量的值并不是它所指向的对象本身,而是该对象的引用,这句话 听起来可能有点让人犯晕,举个例子来说,String str = new String("aaa"); 这条语句的意思是 new 了一个值为 "aaa" 的字符串对象,然后用一个名字叫 str 的对象变量来指向它,保存它的引用,假设在内存中 new 出来的这个字符串对象的实际地址为 0xA242, 那么 str 的值实际上是 0xA242。

  现在来看看例子1,假设

  String value1 = "value1: aaa" 的地址为 0xA242,

  String value2 = "value2: bbb" 的地址为 0xA24B,

  然 我们来看看 swapValue(value1, value2); 语句 Java 是怎么执行的。当程序执行到这句语句的时候,JVM 在栈中创建两个临时变量 tmpValue1,tmpValue2,用来接收传进来的 value1 和 value2 的值,而 value1 和 value2 的值分别为 0xA242 和 0xA24B,所以那两个临时变量 tmpValue1和tmpValue2 的值也被赋值为 0xA242 和 0xA24B,此时接下来的三条语句分别是

  tempStr = 0xA242,

  tmpValue1 = 0xA24B,

  tmpValue2 = 0xA242;

  此时 tmpValue1 的值是指向 "value2: bbb" 这个对象的,

  tmpValue2 的值是指向 "value1: aaa" 这个对象,你可以在 swapValue() 方法内部打印 tmpValue1 和 tmpValue2 的值验证一下。

  不 过这里的 tmpValue1和tmpValue2 是在栈中的临时变量,而并不是 main 方法中 value1和value2,main 方法中 value1和value2 的值并没有改变,那这里所谓的值传递是指什么呢?因为 value1 的值是 0xA242("value1: aaa" 这个对象的引用),而并不是 "value1: aaa" 这个对象,传递参数时传递的是 "value1: aaa" 这个对象的引用也就是 value1 的值,所以是值传递。

  例子2也是一样的,假设

  Person person = new Person("张三", 20) 的地址为 0xA242,

  那 么 person 的值是 0xA242, 那么通过调用 changePerson(person); 将 0xA242 传递给 tmpPerson, 也就是 tmpPerson 此时的值为 0xA242 也就是 new Person("张三", 20) 这个对象的引用,也就是说 tmpPerson 指向 new Person("张三", 20) 对象,对 tmpPerson 引用对象的修改实际上就是对 person 引用对象的修改,这看起来很想引用传递的概念,但实际上是值传递,为什么呢?因为在参数传递过程中传递的是 person 的值,也就是 0xA242。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值