前言

这几天在整理java基础知识方面的内容,对于值传递还不是特别理解,于是查阅了一些资料和网上相关博客,自己进行了归纳总结,最后将其整理成了一篇博客。

值传递

值传递是指在调用函数时将实际参数复制一份传递给形参,这样在函数中对形参的修改将不会影响到实际参数的值。

引用传递

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

我们可以使用一段程序来验证Java中只有值传递

/**

* 验证java中只有值传递

* Dmego 2018-8-27

*/

class User{

private String name;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

public class TestValue {

public static void change(User user2,int a2){

System.out.println("改变之前:"+user2.getName()+",a2="+a2);

user2.setName("李四"); //改变 user2 的 name 值

a2 = 10; //改变 a2 的值

System.out.println("改变之后:"+user2.getName()+",a2="+a2);

user2 = new User(); //将 user2 重新指向一个新对象

user2.setName("王五");

System.out.println("重新指向一个新对象后:"+user2.getName());

}

public static void main(String[] args){

User user1 = new User();

user1.setName("张三"); //初始化 user1 的 name 为张三

int a1 = 5; //初始化 a1 的值为 5

change(user1,a1); //调用方法验证传值方式

System.out.println("调用方法后:"+user1.getName()+",a1="+a1);

}

}

运行这段程序,输出结果为:

改变之前:张三,a2=5

改变之后:李四,a2=10

重新指向一个新对象后:王五

调用方法后:李四,a1=5

结果分析

下面我们以上图为辅助,来分析这段程序,首先我们定义了一个User类,然后在测试类中实例化了一个User对象,名为user1,并且为其赋值name = ‘张三‘,此时在内存中如图1所示,实例化一个对象相当于在堆中开辟了一块内存,内存地址为017,此时这个对象的引用为user1,内存地址为001,它保存了该对象在内存中的地址,也就是指向了该对象。接下了,我们调用方法changeVaulue(),来尝试改变user1的name值以此验证java中的传值方式。

我们将user1作为实参传给changeValue()方法,形参user2来接受这个实参,在这里就体现出了两种传参方式的不同。如果是按值传递,那么就像定义的那样,如图2所示,user2是user1的一份副本,也就是说在传递参数时,将user1(本身是一个对象的引用),复制了一份,名为user2,它同样也是一个对象的引用,并且user1和user2此时指向同一个对象。而如果是引用传递,也如同定义的那样,如图5所示,在传递参数时,是直接将user1传递给了形参,只是换了一个名字叫做user2,但是本质上user1和user2其实是同一个。它是一个对象的引用。

接着来分析输出的结果,不管是按值传递还是引用传递,第1行输出的结果一定都是张三,因为都是指向同一个对象。对于第2行输出,我们还是无法判断是哪种方式,因为都是改变同一个对象,值也会改变;关键在于第3行输出和第4行输出,此时,我们将user2重新指向了一个新的对象,并且为这个对象赋值name = ‘王五‘,如果是引用传递的方式,那么user1同样也会改变指向,指向新的这个对象,最后一行调用方法之后输出的结果将会和第3行一样是王五,但是事实输出的是李四,这表明user1和user2其实并不是同一个。真实的调用过程如 图2~图4所示,这样才会使得user2指向一个新的对象后,user1指向的对象并没有改变,还是原来那个对象。

对于基本类型的参数来说,a1的值最后没有改变,说明在执行方法时,a2是a1的一个副本。对于引用类型的参数来说,例如User对象,在调用方法时,实际上是将其引用user1作为实际参数,那么传递给形参的将是该引用的一份副本引用user2,虽然说这是两份引用(好比a1与a2的关系)。但是却指向同一个对象,所有的操作也都是对这同一个对象而言的。

最后举一个例子来形象的说明这一切,假如你有一把你房间的钥匙,并且在上面刻上了你的名字,这个过程好比给一个int类型的a1初始化值为5。你的朋友和你关系非常好,想要你房间的钥匙,此时你并没有直接把你的钥匙给他,而是复制了一把新的钥匙,这个钥匙也能开你的房间的门。而你的朋友在这把新钥匙上刻上了他的名字。这个过程就好比调用change()方法,把a1复制了一份赋值给a2,此时修改a2和a1没有任何关系,你朋友在新钥匙上刻他名字也不会影响你手上那把原始的钥匙。关键是这两把钥匙都能开你的房间,就好比user1和user2都指向同一个对象。此时你朋友用这把新钥匙打开了你的房间,将你房间电视机砸了。这个过程好比改名李四。这时你拿着你的钥匙打开你房间必然会看到这样的场景——电视机被砸了。就如同调用方法后user1变成了李四。在调用方法的过程中,最后user2重新指向了一个新的对象,这就好比你的朋友将你复制给他的钥匙再次进行了加工,此时不能开你房间的门,但是能开他自己的房间,他用这把钥匙开自己的房间然后把自己的电视砸了这并不会影响到你房间的电视,也就是说最后user1的名字并不会变成王五。这就是java中的值传递。当然了,如果是引用传递,那么这个例子中从头到尾将会只有一把钥匙,最后的结果也将会不同。

尾声

通过以上分析我们可以知道。Java中只有值传递这一种方式,只不过对于引用类型来说,传递的参数是对象的引用罢了。

java只有值传递_为什么说java中只有值传递相关推荐

  1. java反射api研究_深入研究Java 8中的可选类API

    java反射api研究 作为Java程序员,我们所有人都经历了以下情况:我们调用一个方法来获取某个值,然后代替直接对返回值调用某些方法,我们首先必须检查返回值是否不为null,然后在返回值. 这是像G ...

  2. java内存模型浅析_浅谈java内存模型

    不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的.其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改.总结jav ...

  3. java 引用传递_详解java的值传递、地址传递、引用传递

    详解java的值传递.地址传递.引用传递 一直来觉得对值传递和地址传递了解的很清楚,刚才在开源中国上看到一篇帖子介绍了java中的值传递和地址传递,看完后感受颇深.下边总结下以便更容易理解. 按照以前 ...

  4. java只有值传递_为什么说java只有值传递?

    如果你学的第一门程序语言是java可能对这个传递方式没有那么敏感,如果学了c或c++,然后再学java,那么可能对这个问题会感到困惑. 1.值传递与引用传递的概念 在将传递方式之前先理解一下形参与实参 ...

  5. java是引用传递还是值传递_流言终结者:Java是引用传递还是值传递?

    前言 今天聊一个很小的话题,引用传递和值传递.为什么拉出这个话题呢?因为自己太菜吧-在这上边栽了跟头.所以今天就聊一聊Java中是引用传递还是值传递. 正文 小A:MDove,我有一个疑问:Java的 ...

  6. java继承和引用_浅谈Java继承、传递

    一.继承 1. 继承的概念: 子类继承父类,表明子类是一种特殊的父类,并且具有父类所不具有的一些属性或方法. 2. 继承中的初始化顺序: 从类的结构上而言,其内部可以有如下四种常见形态:属性(包括类属 ...

  7. java中怎么把两个JTextfield中的数字相加的值放到另一个JTextfield?_如何将jtextfield中的值解析为整数并对其执行一些数学操作?...

    所以,我一直在尝试用Swing在Java中制作一个CelsiUS转换器,并坚持从 JTextField 把它解析成一个整数,这样我就可以对它执行一个方程.如果我把它作为 String 我不能做任何数学 ...

  8. java redis hash存取_我爱java系列---【redis中如何存取hash类型的值(key field value)】...

    @Servicepublic class CartServiceImpl implementsCartService {private static final String CART="C ...

  9. java不同垃圾回收器_细述 Java垃圾回收机制→Types of Java Garbage Collectors

    本文非原创,翻译自Types of Java Garbage Collectors 在Java中为对象分配和释放内存空间都是由垃圾回收线程自动执行完成的.和C语言不一样的是Java程序员不需要手动写垃 ...

最新文章

  1. 20145227鄢曼君《网络对抗》逆向及Bof基础
  2. c++多态相关面试题
  3. pta_l1-6(连续因子)
  4. 两平面平行方向向量关系_一文读懂 GDT 中的平面度
  5. C# 9 新特性 —— 增强的模式匹配
  6. 51nod1551-集合交易【hall定理,最大权闭合图,网络流】
  7. Linux: terminal 终端生存指南
  8. LeetCode887. 鸡蛋掉落
  9. 智能搜索推荐模型预估框架的建设及在美团点评的实践
  10. 同济保研计算机,同济大学保研率28%,保研高校前四:复旦、北大、交大、清华...
  11. QT 创建鼠标右键菜单
  12. MAC下安装NDKR10e
  13. BZOJ2151 种树
  14. paip.python错误解决12
  15. 18.Linux软件安装之Rpm安装
  16. cNode------路由设置以及项目基本框架搭建
  17. 计算机网络技术思维导图幕布全整理(附网页版链接)
  18. Unity笔记—常用小功能整合
  19. 华为云服务器参数配置文件,华为云服务器参数配置文件
  20. NOIp2018停课集训总结

热门文章

  1. 5G商用牌照近期发放;华为削减手机订单;苹果、亚马逊、Google遭调查 | 极客头条...
  2. 第二届字节跳动夏令营启动全球报名,图灵奖得主授课
  3. 势逼 React Native,跨平台开发框架 Flutter 很凶猛 | 码书
  4. 你所掌握的开源,也许都是错的!
  5. 滴滴,一个连接者的责任边界
  6. 为什么滴滴天猫都玩上了大数据“杀熟”的套路?
  7. 这个华人程序员是如何 6 个月狂赚 125 亿的?
  8. 猎豹移动傅盛:区块链将重塑整个社会关系,CEO恐将职位不保
  9. 年末阿里百度等大厂技术面试题汇总,不可思议!
  10. java与html关联_HTML页和ashx页之间的关联