当前位置: 首页 > news >正文

java 传递 函数_Java 与值传递

问:什么是值传递?什么是引用传递?为什么说 Java 中只有值传递?


一、值传递与引用传递

实参与形参:

  • 实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用被调函数时,函数名后面括号中的参数称为“实际参数”。
  • 形式参数:在定义函数名和函数体时使用的参数,目的是用来接收调用此函数时传入的参数。

值传递与引用传递:

  • 值传递:是指在调用函数时,将实际参数复制一份,通过形参传递到函数中。这时形参接收到的内容是实参的一个副本,这样在函数中如果对形参进行修改,不会影响到实际参数。
  • 引用传递:是指在调用函数时,将实际参数的地址传递到函数中,那么在函数中对参数进行的修改,将会影响到实际参数。

重点的区别在于:

d77dbce90f7ba871a73ac3e930b29c1d.png

二、Java 中的值传递

这里需要清楚 JVM 内存的划分及职能,即:

  1. 虚拟机栈;
  2. 堆;
  3. 程序计数器;
  4. 方法区;
  5. 本地方法栈;

已知,JVM 会给每个线程分配一个 Java 栈,当执行一个方法时,JVM 会往该栈中压入一个栈帧。

1. 对于基本数据类型

在方法中,基本数据类型的形参及变量(称为局部变量)的名字和值都存储于栈中。在该方法被调用时,会为形参在栈帧中开辟一块内存,将实参值复制给形参,然后形参和实参之间便没有了关联。

即,此后在方法中对形参的操作不会影响到原来的实参。 例:

public static void main(String[] args) {
    int a = 21;
    intTest(a);
    System.out.println("方法执行后的a: "+a);
}

public static void intTest(int var){
    // 将实参值复制给形参
    System.out.println("传入的形参var:"+var);
    
    // 在方法中对形参的操作不会影响到原来的实参
    var = 23;
    System.out.println("方法内重新赋值后的形参var:"+var);
}

运行结果:

传入的形参var:21
方法内重新赋值后的形参var:23
方法执行后的a: 21

2. 对于引用数据类型(对象类型)

Java 里面的变量,要么是基本数据类型,要么是指向对象实例的引用类型,绝对不会是一个对象。

对于引用数据类型的对象,变量的名和值均存储在栈中,变量值存储的是对象的地址,对象的实际内容存储于堆(堆区是共享的)中。在该方法被调用时,会为形参在栈帧中开辟一块内存,将实参值复制给形参,即把实参指向的对象的地址复制给了形参:

1.此后在方法内部,如果没有改变形参值(对象的地址),那么可以通过该形参操作原实参指向的堆中的对象。这样虽然原对象的属性可能发生变化,但原实参的值(指向的地址)并没有发生变化。例:

// 设 Student 类对象有 name 和 age 两个属性

public static void main(String[] args) {
    Student student = new Student("张三",18);
    System.out.println("原对象的hashCode值:"+student.hashCode());
    referenceTest(student);

    System.out.println("测试后的原对象:"+student);
    System.out.println("测试后原对象的hashCode值:"+student.hashCode());
}

public static void referenceTest(Student stu){
    System.out.println("改变前形参指向对象的hashCode值:"+stu.hashCode());

    stu.setName("李四");
    System.out.println("改变后形参指向的对象:"+stu);
    System.out.println("改变后形参指向对象的hashCode值:"+stu.hashCode());
}

运行结果:(这里 hashCode 值可代表地址)

原对象的hashCode值:21685669

改变前形参指向对象的hashCode值:21685669
改变后形参指向的对象:Student{name='李四', age=18}
改变后形参指向对象的hashCode值:21685669

测试后的原对象:Student{name='李四', age=18}
测试后原对象的hashCode值:21685669

2.如果该形参指向其它对象,或者指向新 new 的对象,那么形参值变为新对象的内存地址。此后通过该形参操作的会是新的对象,原实参的值(指向的地址)不会发生变化。例:

// 设 Student 类对象有 name 和 age 两个属性

public static void main(String[] args) {
    Student student = new Student("张三",18);
    System.out.println("原对象的hashCode值:"+student.hashCode());
    referenceTest(student);

    System.out.println("测试后的原对象:"+student);
    System.out.println("测试后原对象的hashCode值:"+student.hashCode());
}

public static void referenceTest(Student stu){
    System.out.println("改变前形参指向对象的hashCode值:"+stu.hashCode());

    stu = new Student("王五",21);
    System.out.println("改变后形参指向的对象:"+stu);
    System.out.println("改变后形参指向对象的hashCode值:"+stu.hashCode());
}

运行结果:(这里 hashCode 值可代表地址)

原对象的hashCode值:21685669

改变前形参指向对象的hashCode值:21685669
改变后形参指向的对象:Student{name='王五', age=21}
改变后形参指向对象的hashCode值:2133927002  // 有变化

测试后的原对象:Student{name='张三', age=18}
测试后原对象的hashCode值:21685669

即,此后在方法中对形参的操作并不会影响到原来的实参值(原对象的地址)。


参考博文,推荐阅读:

  • 为什么说Java中只有值传递。
  • 这一次,彻底解决Java的值传递和引用传递 - 掘金
  • 柳树:用画小狗的方法来解释Java值传递

如有问题,欢迎交流~ (完)

博客原文:Deecyn's Blog

相关文章:

  • 乒乓球比赛赛程_恒天重工郑州区域2019年度职工乒乓球团体锦标赛圆满落幕
  • a标签移动上去没有下划线怎么设置_seo优化师是怎么对文章网页标题命名的?...
  • is属性用法 vue_vue组件讲解(is属性的用法)
  • db2 update覆盖更新_DLA访问TableStore的性能调优Hints、支持单字段update等
  • dubbo调用service后返回对象null_你玩了3年Dubbo,给我聊聊它的服务暴露过程?
  • 托福试卷真题_托福考试历年真题测试
  • vscode安装旧版本插件_vscode 常用插件安装
  • 联想笔记本键盘排线_笔记本排线坏了怎么修?笔记本排线接触不良怎么办?
  • eclipse导入mysql8.0驱动_eclipse jdbc连接MySQL8.0数据库详解
  • arcgis导入excel字段不显示_ArcGis属性字段操作技巧(上下标显示、批量删除)
  • 筛数方法相关系数_Spearman相关系数的变量筛选方法
  • miui删除内置不卡米教程_小米MIUI免ROOT一键删除系统内置软件
  • ffmpeg 录制指定窗口_音视频最简单基础知识一篇文章带你入门《ffmpeg干货》
  • es6 filter函数的用法_ES6新增数组方法
  • 记录方法用时_发明专利|一种微电网继电保护方法
  • 0基础学习移动端适配
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • Babel配置的不完全指南
  • ES6之路之模块详解
  • HTML-表单
  • js
  • laravel5.5 视图共享数据
  • Linux后台研发超实用命令总结
  • maven工程打包jar以及java jar命令的classpath使用
  • node.js
  • Vue 2.3、2.4 知识点小结
  • vue--为什么data属性必须是一个函数
  • webpack入门学习手记(二)
  • 百度小程序遇到的问题
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 搭建gitbook 和 访问权限认证
  • 浮动相关
  • 关于springcloud Gateway中的限流
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 深入浅出webpack学习(1)--核心概念
  • 微信小程序实战练习(仿五洲到家微信版)
  • 写给高年级小学生看的《Bash 指南》
  • Semaphore
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 阿里云重庆大学大数据训练营落地分享
  • 第二十章:异步和文件I/O.(二十三)
  • 树莓派用上kodexplorer也能玩成私有网盘
  • %@ page import=%的用法
  • (二)WCF的Binding模型
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (学习日记)2024.02.29:UCOSIII第二节
  • (一)插入排序
  • (转)C#调用WebService 基础
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • ***详解账号泄露:全球约1亿用户已泄露
  • *Django中的Ajax 纯js的书写样式1
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .NET Project Open Day(2011.11.13)
  • .Net Redis的秒杀Dome和异步执行