前言

这几天在整理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,它保存了该对象在内存中的地址,也就是指向了该对象。接下了,我们调用方法change(),来尝试改变user1name值以此验证java中的传值方式。

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

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

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

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

尾声

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

java中传值方式的个人理解的更多相关文章

  1. java中传值及引伸深度克隆的思考(说白了Java只能传递对象指针)

    java中传值及引伸深度克隆的思考 大家都知道java中没有指针.难道java真的没有指针吗?句柄是什么?变量地址在哪里?没有地址的话简直不可想象! java中内存的分配方式有两种,一种是在堆中分配, ...

  2. java中容器的学习与理解

    以前一直对于java中容器的概念不理解,虽然学习过,但始终没有认真理解过,这几天老师提出了这样一个问题,你怎么理解java中的容器.瞬间就蒙了.于是各种搜资料学习了一下,下面是我学习后整理出来的的一些 ...

  3. java中GET方式提交和POST方式提交

    java中GET方式提交的示例: /** * 获取关注列表; * @return */ @SuppressWarnings("unchecked") public static A ...

  4. java中多种方式读文件

    转自:http://www.jb51.net/article/16396.htm java中多种方式读文件 一.多种方式读文件内容. 1.按字节读取文件内容 2.按字符读取文件内容 3.按行读取文件内 ...

  5. 浅谈对java中传参问题的理解

    之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...

  6. JAVA中关于并发的一些理解

    一,JAVA线程是如何实现的? 同步,涉及到多线程操作,那在JAVA中线程是如何实现的呢? 操作系统中讲到,线程的实现(线程模型)主要有三种方式: ①使用内核线程实现 ②使用用户线程实现 ③使用用户线 ...

  7. 关于Java中形参与实参的理解

    今天阅读了一个写的非常棒的博文,通过此博文再次复习了Java中参数传递的知识(即值传递与引用传递的区别).参考网站http://www.cnblogs.com/binyue/p/3862276.htm ...

  8. java参数传值方式

     java参数有值类型和引用类型两种.所以java参数的传值也就从这两个方面分析. 从内存模型来说参数传递更为直观一些,这里涉及到两种类型的内存:栈内存(stack)和堆内存(heap).   基本类 ...

  9. 关于java中Static关键字的加强理解

    static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列 ...

随机推荐

  1. 修改idea打开新窗口的默认配置

    使用idea开发maven项目时,发现使用新窗口创建一个项目时,例如file-settings的maven库配置都是用的用户下的maven库,如何配置一个全局的maven配置呢,操作如下: File- ...

  2. Python——pytessercat识别简单的验证码

    什么是验证码 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computersand Humans Apart” (全自动 ...

  3. Linux学习笔记之十————Linux常用服务器构建之ftp服务器

    p服务器介绍 FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为“文传协议”. 用于Internet上的控制文件的双向传输. 同时,它也是一个应用程序(Ap ...

  4. js排序问题

    1.直接排序 var arr = [1,3,2,5]; function compare(a,b){ return a - b;//从小到大 return b - a;//从大到小 } console ...

  5. [java初探09]__关于java的包装类

    前言 在Java语言的学习过程中,我们逐渐的理解了Java面向对象的思想,与类和对象的应用.但是在基本数据类型的使用上,我们无法将其定义为一个对象,通过使用对象的方法来使用它们,但是Java语言的思想 ...

  6. 从零开始学 Web 之 CSS3(七)多列布局,伸缩布局

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  7. Java并发编程笔记之Timer源码分析

    timer在JDK里面,是很早的一个API了.具有延时的,并具有周期性的任务,在newScheduledThreadPool出来之前我们一般会用Timer和TimerTask来做,但是Timer存在一 ...

  8. leetcode — container-with-most-water

    /** * Source : https://oj.leetcode.com/problems/container-with-most-water/ * * Created by lverpeng o ...

  9. SpringBoot(2) Json框架 -- Jackson返回结果处理

    一.常用框架 阿里 fastjson,谷歌gson等 JavaBean序列化为Json,性能:Jackson > FastJson > Gson > Json-lib 同个结构 Ja ...

  10. 趁webpack5还没出,先升级成webpack4吧

    上一次将webpack1升级到3,也仅是 半年前,前端工具发展变化太快了,如今webpack4已经灰常稳定,传说性能提升非常高,值得升级. 一直用着的webpack3越来越慢,一分多钟的编译时间简直不 ...