问: 什么是值传递?什么是引用传递?为何说 Java 中只有值传递?java
实参与形参:函数
值传递与引用传递:post
重点的区别在于:测试
方面 | 值传递 | 引用传递 |
---|---|---|
根本区别: | 会建立副本(copy) | 不会建立副本 |
因此: | 函数中没法改变原始对象 | 函数中能够改变原始对象 |
这里须要清楚 JVM 内存的划分及职能,即:线程
已知,JVM 会给每一个线程分配一个 Java 栈,当执行一个方法时,JVM 会往该栈中压入一个栈帧。code
在方法中,基本数据类型的形参及变量(称为局部变量)的名字和值都存储于栈中。在该方法被调用时,会为形参在栈帧中开辟一块内存,将实参值复制给形参,而后形参和实参之间便没有了关联。对象
即,此后在方法中对形参的操做不会影响到原来的实参。 例:内存
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); }
运行结果:get
传入的形参var:21 方法内从新赋值后的形参var:23 方法执行后的a: 21
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
即,此后在方法中对形参的操做并不会影响到原来的实参值(原对象的地址)。
参考博文:
若有问题,欢迎交流~ 欢迎您的点赞、收藏和评论!