网站首页 > java教程 正文
问: 什么是值传递?什么是引用传递?为什么说 Java 中只有值传递?
一、值传递与引用传递
实参与形参:
- 实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用被调函数时,函数名后面括号中的参数称为“实际参数”。
- 形式参数:在定义函数名和函数体时使用的参数,目的是用来接收调用此函数时传入的参数。
值传递与引用传递:
- 值传递:是指在调用函数时,将实际参数复制一份,通过形参传递到函数中。这时形参接收到的内容是实参的一个副本,这样在函数中如果对形参进行修改,不会影响到实际参数。
- 引用传递:是指在调用函数时,将实际参数的地址传递到函数中,那么在函数中对参数进行的修改,将会影响到实际参数。
重点的区别在于:
方面 值传递 引用传递 根本区别: 会创建副本(copy); 不会创建副本 所以: 函数中无法改变原始对象; 函数中可以改变原始对象
二、Java 中的值传递
这里需要清楚 JVM 内存的划分及职能,即:
- 虚拟机栈
- 堆
- 程序计数器
- 方法区
- 本地方法栈
已知,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
即,此后在方法中对形参的操作并不会影响到原来的实参值(原对象的地址)。
参考博文:
- https://mp.weixin.qq.com/s/F7Niaa7nD1tLApCEGKAj4A
- https://juejin.im/post/5bce68226fb9a05ce46a0476
- https://zhuanlan.zhihu.com/p/29074454
如有问题,欢迎交流~
欢迎您的点赞、收藏和评论!
猜你喜欢
- 2024-11-11 挨个举例子告诉你Java中的参数传递,我就不信你还不明白了
- 2024-11-11 Java值传递机制(java传值方式)
- 2024-11-11 Java面试-为什么 Java 只有值传递?
- 2024-11-11 Stack Overflow上188W+程序员都关注的问题
- 2024-11-11 为什么说Java不存在引用传递?(javax不存在)
- 2024-11-11 一份2021年的java面试题(java常见面试题)
- 2024-11-11 互联网大厂面试系列-为什么说在Java方法参数调用只有值传递呢?
- 2024-11-11 一文搞懂参数传递原理(参数传递的三种方式)
- 2024-11-11 Java程序员想年后跳槽,对JVM没有深入的理解,我劝你还是别跳了
- 2024-11-11 JAVA校招题基础知识点复习第二天(引用传递的本质是什么?)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)