Java之中的参数传递,只有按值传递!!!

传递类型

按值传递:就是把原来的参数的值,拷贝一份,将这个拷贝的值修改,而原来的旧的值不会修改。

引用传递:就是将参数的地址拿来使用,不去拷贝,直接在这个地址上操作,这样的话,就会把原来的值也修改了。

Java参数传递是值传递还是引用传递?

当一个对象被当作参数传递到一个方法后,在此方法内可以改变这个对象的属性,那么这里到底是值传递还是引用传递?

答:是值传递。Java 语言的参数传递只有值传递。当一个实例对象作为参数被传递到方法中时,参数的值就是该对象的引用的一个副本。指向同一个对象,对象的内容可以在被调用的方法内改变,但对象的引用(不是引用的副本) 是永远不会改变的。

值传递的证明

如果是引用传递,那么我们修改操作的时候,直接是对地址进行操作,意味着我们的操作,都是直接对这个地址上的内容进行修改,所以这个修改是必然生效的,而如果是值传递,那么意味着,我传过去的参数,只是一个值,我们知道,一个对象是分配在内存地址上的,而如果只是传了一个参数的话,这就意味着,我们的参数原先的位置等信息,没有传递过去,而只是传了一个拷贝的值,这个拷贝的值,是在一个新的地址上,我们对一个对象进行更新操作,这必然意味着我们直接对这个地址上所承载和分配的内容进行了修改,而如果只是值传递,那么就是将我们的参数的值,进行了一个拷贝,而对原来的值,没有改动,没有改动原来地址上的内容。所以按照这个而言,值传递,不会修改参数的原来的内容。那么是不是这样呢?

/**

* @Author zgy

* @Date 2020/6/15

* @Description 总的结论: Java是按照值传递的,而不是按照引用,

* 按值传递: 就是把原来的参数的值,拷贝一份,将这个拷贝的值修改,而原来的旧的值不会修改

* 引用传递:就是将参数的地址拿来使用,不去拷贝,直接在这个地址上操作,这样的话,就会把原来的值也修改了

*/

public class TransferParam {

public static void main(String[] args) {

// 基本类型的值传递

System.out.println("===========基本类型的值传递============");

int age = 22;

System.out.println("调用changeData(int data)方法前: " + age);

changeDataBasic(age);

System.out.println("调用changeData(int data)方法后: " + age + "\n");

// 基本类型的值传递, String

System.out.println("===========基本类型的值传递:String============");

String name = "张三";

System.out.println("调用changeString(String str)方法前: " + name);

changeString(name);

System.out.println("调用changeString(String str)方法后: " + name + "\n\n");

// 对象类型的值传递

System.out.println("+++++++++++对象类型的值传递++++++++++++++");

Map map = new HashMap<>();

map.put("name", "李小龙");

System.out.println("调用changeDataObject(Map map)方法前: " + map);

changeDataObject(map);

System.out.println("调用changeDataObject(Map map)方法后: " + map + "\n");

// 对象类型的值传递, 普通的对象

System.out.println("+++++++++++对象类型的值传递:People++++++++++++++");

Map info = new HashMap<>();

info.put("address", "北京朝阳");

info.put("home", "四川成都");

People people = People.builder().age(22).name("lee").info(info).build();

System.out.println("调用changePeople(People people)方法前: " + people);

changePeople(people);

System.out.println("调用changePeople(People people)方法后: " + people);

}

public static void changeDataBasic(int data) {

data = 100;

System.out.println("方法中: " + data);

}

public static void changeDataObject(Map map){

Map testMap = new HashMap<>();

testMap.put("name", "zhangsan");

map = testMap;

System.out.println("方法中: " + map);

}

public static void changeString(String str){

str ="Hello world!";

System.out.println("方法中: " + str);

}

public static void changePeople(People people){

Map info2 = new HashMap<>();

info2.put("address", "北京");

info2.put("home", "四川雅安");

People people2 = People.builder().age(22).name("lee").info(info2).build();

people = people2;

System.out.println("方法中: " + people2);

}

}

@Data

@Builder

class People {

private String name;

private Integer age;

private Map info;

}

我们分别对普通的基本类型,String对象,Map对象和自定义的People对象,进行了测试,都证明了是值的传递,而非引用传递,输出的结果如下:

===========基本类型的值传递============

调用changeData(int data)方法前: 22

方法中: 100

调用changeData(int data)方法后: 22

===========基本类型的值传递:String============

调用changeString(String str)方法前: 张三

方法中: Hello world!

调用changeString(String str)方法后: 张三

+++++++++++对象类型的值传递++++++++++++++

调用changeDataObject(Map map)方法前: {name=李小龙}

方法中: {name=zhangsan}

调用changeDataObject(Map map)方法后: {name=李小龙}

+++++++++++对象类型的值传递:People++++++++++++++

调用changePeople(People people)方法前: People(name=lee, age=22, info={address=北京朝阳, home=四川成都})

方法中: People(name=lee, age=22, info={address=北京, home=四川雅安})

调用changePeople(People people)方法后: People(name=lee, age=22, info={address=北京朝阳, home=四川成都})

值传递的分析

如下作为分析,在我们对基本类型操作的时候,比如如下的age=22,在调用changeDataBasic方法的前后,其实就相当于在内存中把age复制了一份,在调用之中,传递的是拷贝的一份,这拷贝的一份,我们可以在changeDataBasic方法之中,随意操作,但是它影响不了外面的age的值,因为这已经是两份对象。

public static void main(String[] args) {

System.out.println("===========基本类型的值传递============");

int age = 22;

System.out.println("调用changeData(int data)方法前: " + age);

changeDataBasic(age);

System.out.println("调用changeData(int data)方法后: " + age + "\n");

}

public static void changeDataBasic(int data) {

data = 100;

System.out.println("方法中: " + data);

}

等号"="的操作含义

对于基本数据类型来说 “=”赋值操作是直接改变内存地址(存储单元)上的值。

对于引用类型来说 “=” 赋值操作是改变引用变量所指向的内存地址(上文中存储单元)。

容易导致混淆的赋值

/**

* @Author zgy

* @Date 2020/6/15

* @Description 总的结论: Java是按照值传递的,而不是按照引用,

* 按值传递: 就是把原来的参数的值,拷贝一份,将这个拷贝的值修改,而原来的旧的值不会修改

* 引用传递:就是将参数的地址拿来使用,不去拷贝,直接在这个地址上操作,这样的话,就会把原来的值也修改了

*

* 虽然值传递和引用传递尘埃落定,在Java之中只有值传递,但是有个操作很容易造成迷惑,就是赋值,以如下基本类型和Map对象来演示

*/

public class TransferParam2 {

public static void main(String[] args) {

// 基本类型的值传递

System.out.println("===========基本类型的值传递============");

int age = 22;

System.out.println("调用changeData(int data)方法前: " + age);

changeDataBasic(age);

System.out.println("调用changeData(int data)方法后: " + age + "\n");

// 对象类型的值传递

System.out.println("===========对象类型的值传递============");

Map map = new HashMap<>();

map.put("name", "李小龙");

System.out.println("调用changeDataObject(Map map)方法前: " + map);

changeDataObject(map);

System.out.println("调用changeDataObject(Map map)方法后: " + map + "\n\n");

// 基本类型的值传递, 但是赋值行为改变了作用范围

System.out.println("++++++++++++基本类型的值传递: 返回值赋值修改了值+++++++++++++");

int age2 = 22;

System.out.println("调用changeDataReturn(int data)方法前: " + age2);

// 赋值行为修改了原先的值

age2 = changeDataBasicReturn(age);

System.out.println("调用changeDataReturn(int data)方法后: " + age2 + "\n");

// 对象类型的值传递, 但是赋值行为改变了作用范围

System.out.println("++++++++++++对象类型的值传递: 返回值赋值修改了值++++++++++++++");

Map map2 = new HashMap<>();

map2.put("name", "陈真");

System.out.println("调用changeDataObjectReturn(Map map)方法前: " + map2);

// 赋值行为修改了原先的值

map2 = changeDataObjectReturn(map2);

System.out.println("调用changeDataObjectReturn(Map map)方法后: " + map2 + "\n\n");

}

// 这是空方法, 没有赋值行为, 对拷贝内容的修改, 仅仅局限于方法内, 返回是void, 对外不造成影响

public static void changeDataBasic(int data) {

data = 100;

System.out.println("方法中: " + data);

}

public static void changeDataObject(Map map) {

Map testMap = new HashMap<>();

testMap.put("name", "zhangsan");

map = testMap;

System.out.println("方法中: " + map);

}

// 该方法有返回值, 值传递中拷贝的内容, 在修改之后, 可以通过该方法进行赋值, 所以会对外造成影响

public static int changeDataBasicReturn(int data) {

data = 100;

System.out.println("方法中: " + data);

return data;

}

public static Map changeDataObjectReturn(Map map) {

Map testMap = new HashMap<>();

testMap.put("name", "zhangsan");

map = testMap;

System.out.println("方法中: " + map);

return map;

}

}

输出的结果如下

===========基本类型的值传递============

调用changeData(int data)方法前: 22

方法中: 100

调用changeData(int data)方法后: 22

===========对象类型的值传递============

调用changeDataObject(Map map)方法前: {name=李小龙}

方法中: {name=zhangsan}

调用changeDataObject(Map map)方法后: {name=李小龙}

++++++++++++基本类型的值传递: 返回值赋值修改了值+++++++++++++

调用changeDataReturn(int data)方法前: 22

方法中: 100

调用changeDataReturn(int data)方法后: 100

++++++++++++对象类型的值传递: 返回值赋值修改了值++++++++++++++

调用changeDataObjectReturn(Map map)方法前: {name=陈真}

方法中: {name=zhangsan}

调用changeDataObjectReturn(Map map)方法后: {name=zhangsan}

如果单纯从上述的代码之中看,那我们很可能就会认为是引用传递起了作用,但是我们要知道,引用传递起作用是发生在一个整体的同一个步骤之中,而不像此处,先传值,然后再去通过方法的返回值,去赋值,这样就是两个步骤了,这种操作,会让人一下子有点迷惑,但是其实还是很好理解的,就是说,一步到位的就一定是引用传递,而我们只需记住,Java之中只有按值传递,所有的参数传递操作,都是传递了值的拷贝,也就是值的内容,而非对象的地址。

参考:

java map 参数传递_Java参数传递分析相关推荐

  1. java输出值_java参数传递(超经典)(强烈建议自己先写出程序的输出值)

    Java中的参数传递机制一直以来大家都争论不休,究竟是"传值"还是"传址(传引用)",争论的双方各执一词,互不相让.不但"菜鸟"们一头雾水, ...

  2. java map 教程_Java Map接口

    Java Map接口 在本教程中,我们将学习Java Map接口及其方法. Java collections框架的Map接口提供了Map数据结构的功能. 它实现了Collection接口. map的工 ...

  3. java map包_java Map

    java Map CreateTime--2017年5月26日08:44:16 Author:Marydon 四.java数据类型之Map 需要导入包: importjava.util.Map;imp ...

  4. java map原理_Java HashMap底层原理分析

    前两天面试的时候,被面试官问到HashMap底层原理,之前只会用,底层实现完全没看过,这两天补了补功课,写篇文章记录一下,好记性不如烂笔头啊,毕竟这年头脑子它记不住东西了哈哈哈.好了,言归正传,今天我 ...

  5. java visualvm 教程_Java性能分析神器--VisualVM Launcher[1]

    Java性能分析神器1--VisualVM Launcher VisualVM 当你日复一日敲代码的时候,当你把各种各样的框架集成到一起的时候,看着大功告成成功运行的日志,有没有那么一丝丝迷茫和惆怅: ...

  6. java map深拷贝_java 实现Map的深复制

    在java中有一个比较有趣的特性,在对对象进行=赋值,或者clone时候一般都是我们所说的浅复制, Object A = B; 也就是说我们获取的并非在堆中重新分配的一块内存,而是一个指向原有数据内存 ...

  7. java map 队列_Java:queue队列,map集合

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 Queue: 基本上,一个队列就是一个先入先出(FIFO)的数据结构 Queue接口与List.Set同一级别,都是继承了Collection接口.Lin ...

  8. java map 内存_java 使用对象和Map保存字符串占用存储空间对比

    对整体堆大小的影响 创建对象情况 已使用的堆大小 没有使用任何对象 95,805,912 个字节 使用map10000000个相同字符串 1,017,388,888 个字节 创建10000000个空对 ...

  9. java map 排序_java集合框架面试题大集合

    1.介绍JAVA 中的Collection FrameWork(及如何写自己的数据结构)[基础] 答:Collection FrameWork 如下: Collection: ├List │├Link ...

最新文章

  1. 关于python的字符串大小转换函数:capitalize() title() upper() swapcase()
  2. SIMILAR:现实场景中基于子模块信息度量的主动学习
  3. SAP MM ME21N 创建PO时报错 - Net price in CNY becomes too large – 之对策
  4. 客户端爬取-答网友问
  5. 东芝3005您的机器需要保养_两联供之东芝中央空调天氟地水详细讲解
  6. oracle中的NVL,NVL2,NULLIF,COALESCE函数使用
  7. MFC的固高环形倒立摆GRIP2002实验平台
  8. 【转】Windows7硬盘安装Linux
  9. Android分辨率比例为1,修改android5.1系统分辨率
  10. MySQL5.7 semi-sync replication功能增强
  11. 微软官方解读 Win11 操作系统
  12. SSH 框架 没加commons-beanutils-1.7.0.jar包的错误提示
  13. 9.卷1(套接字联网API)---基本SCTP套接字编程
  14. OpenCV-图像处理(10、膨胀与腐蚀)
  15. DELMIA软件物流仿真:带曲线转角输送带输送物料的仿真操作方法
  16. setuna.exe在win10下使用,桌面自动放大问题
  17. 教你写Linux设备驱动程序:一个简短的教程
  18. 怎么给视频去水印?手把手教你去水印
  19. java拍照控件焦距问题,监控摄像头镜头焦距计算方法
  20. 通过用jQuery写一个页面,我学到了什么

热门文章

  1. Win10休眠文件更改存储位置
  2. 逻辑运算符:与,或,非,异或
  3. git 将本地项目关联到远程仓库
  4. 【MySQL集群】——Java程序连接MySQL集群
  5. 高精度地图lanelet2或opendrive转vectormap
  6. Flashback 技术总结(转贴整理)
  7. 02 MSC类设备-基础篇(二)
  8. Linux上类似vbs脚本,VBS脚本常用经典代码收集
  9. asp.net监听输入框值的即时变化onpropertychange、oninput
  10. 心跳异常检测--使用Keras,K折交叉训练CNN一维卷积