java基础:所有参数皆是按值参数

c#中对于参数的传递,有二种处理方式,默认情况下:值类型的参数,按值传递(即:方法体内的参数是原值的副本);引用类型的参数,"加ref关键字后“,按引用传递(即:方法体内的参数,是对象的指针引用,在方法体内修改了对象的属性,方法调用完成后,这种变化也会保持下去).

java虽然也是OO语言,但是这一点有很大不同,不管是“值”类型的简单参数(比如:int),还是“引用”类型的对象参数(比如:Object),参数永远是按值传递(参数永远是原值的副本)。只不过,对于int型的简单参数,比如:5,副本也是5,相当于在内存又开辟一块空间,存储5这个值,但这二个5完全不相关联。而对于对象参数(比如:Object),参数副本应理解成对象指针引用“地址值”的副本,比如:原Object对象在内存中的指针地址为OX0001,则参数为OX0001的另一个副本,因为这二个地址值相同,所以在大多数情况下,方法体内,通过指针地址定位到的对象是同一个,即:方法体内修改对象的属性,该对象就被永远修改了,即使方法调用完成,这种修改的结果也会永远保存下去。这给很多java初学者造成java中参数有按引用传递的错觉。

看下面的示例:

先定义一个测试用的Person类

 1 package com.cnblogs.yjmyzz.test;
 2 
 3 public class Person {
 4     
 5     public Person(){}
 6 
 7     private String name;
 8 
 9     public String getName() {
10         return name;
11     }
12 
13     public void setName(String name) {
14         this.name = name;
15     }
16 
17     public String toString() {
18         return "name:" + name;
19     }
20 
21 }

然后来一个单元测试

 1     @Test
 2     public void testPerson1() {
 3 
 4         Person p1 = new Person();
 5         p1.setName("aaa");
 6         System.out.println(p1); // aaa
 7         System.out.println();
 8 
 9         changePerson1(p1);// xxx
10         System.out.println(p1);// xxx
11 
12     }
13     
14     void changePerson1(Person p) {
15         p.setName("xxx");
16         System.out.println(p);
17         System.out.println();
18     }

运行结果:

name:aaa

name:xxx

name:xxx

如上图所示,这种情况很好理解,p1,p因为值相同,所以根据这个地址值,寻址找到的对象是同一个,改p.name值与改p1.name没什么分别

再来一个版本:

 1 @Test
 2     public void testPerson2() throws InstantiationException,
 3             IllegalAccessException {
 4 
 5         Person p1 = new Person();
 6         p1.setName("aaa");
 7         System.out.println(p1); // aaa
 8         System.out.println();
 9 
10         changePerson2(p1);// yyy
11         System.out.println(p1);// xxx
12     }
13 
14 
15 
16     void changePerson2(Person p) throws InstantiationException,
17             IllegalAccessException {
18         Person newPerson = Person.class.newInstance();
19         newPerson.setName("yyy");
20 
21         p = newPerson;
22 
23         System.out.println(p);
24         System.out.println();
25     }

运行结果:

name:aaa

name:yyy

name:aaa

如上图,刚开始P1,P值相同,但是在ChangePerson2内部,又new了一个Person的新实例:newPerson,修改newPerson.Name,并不会影响P1和P,在最后,将newPerson赋值给p,注意:p只是p1的地址值副本,所以虽然p与newPerson最终指向一样了,但是并不会影响原值p1,所以方法调用完成后,p1.name还是原来的值

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏蜕变

Python 数据类型

Python主要数据类型包括list(列表)、tuple(元组)、dict(字典)和set(集合)等对象,下面逐一介绍这些Python数据类型。

10500
来自专栏淡定的博客

python入门基础语法总结

11330
来自专栏大前端_Web

js浮点数加减乘除

版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/articl...

22630
来自专栏超然的博客

ECMAScript 6 笔记(五)

Iterator接口的目的,就是为所有数据结构,提供了一种统一的访问机制,即for...of循环

13920
来自专栏nnngu

018 final 关键字的用途

final关键字的含义 final在Java中是一个保留的关键字,可以声明成员变量、方法、类以及本地变量。一旦你将引用声明作final,你将不能改变这个引用了,...

37660
来自专栏黑白安全

关于PHP语言在内存中的分配(堆和栈的区别)

本文以PHP语言为例来分析计算机中各段存储区的区别,代码段、堆空间段、代码段、初始化静态常量段。

35920
来自专栏noteless

-1-6 java 异常简单介绍 java异常 异常体系 Throwable 分类 throws和throw 异常处理 自定义异常

异常由来:问题也是现实生活中一个具体事务,也可以通过java 的类的形式进行描述,并封装成对象。

13430
来自专栏IT可乐

深入理解计算机系统(3.8)------数组分配和访问

  上一篇博客我们讲解了汇编语言中过程(函数)的调用实现。理解数据如何在调用者和被调用者之间传递,以及在被调用者当中局部变量内存的分配以及释放是最重要的。那么这...

238100
来自专栏吾爱乐享

java学习之数组元素排序,冒泡排序和选择排序

12840
来自专栏Hongten

python开发_python中str.format()

21620

扫码关注云+社区

领取腾讯云代金券