网站首页 > java教程 正文
值传递: 调用函数时,将实参复制一份传给函数,函数中修改参数时不会影响实参
引用传递:调用函数时,将实参的地址传给函数,函数中修改参数会影响实参。
判断是值传递还是引用传递的标准,和传递参数的类型是没有关系的。
Java中的栈与堆
- 栈:存放基本类型的局部变量,与对象的引用,方法执行结束后栈中的变量和对象的引用消失。
- 堆:存放对象的实例。java中的数组和new出来的对象都是放在堆中的,堆中的对象没有任何引用(就是在栈中没有任何一个变量指向该对象)时会被GC回收。
1-值传递
public class TestNum {
public static void main(String[] args) {
int num = 3;
System.out.println("修改前的num值:"+num);
changeValue(num);
System.out.println("修改后的num值:"+num);
}
private static void changeValue(int num) {
num = 5;
System.out.println("形参num值:"+num);
}
}
结果:
修改前的num值:3
形参num值:5
修改后的num值:3
值传递不是简单的把实参传递给形参,而是,实参建立了一个副本,然后把副本传递给了形参。图中num是实参,然后创建了一个副本temp,把它传递给形参value,修改value值对实参num没有任何影响。
image
2-引用传递
package java_learn;
class User {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User(int age, String name) {
this.age = age;
this.name = name;
}
public User() {
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
public class TestUser {
public static void main(String[] args) {
User user = new User(18, "zhangsan");
System.out.println("修改对象前:"+user);
changeUser(user);
System.out.println("修改对象后:"+user);
}
private static void changeUser(User user) {
user.setAge(20);
user.setName("lisi");
}
}
结果:
修改对象前:User{age=18, name='zhangsan'}
修改对象后:User{age=20, name='lisi'}
可以发现,传过去的user对象,属性值被改变了。由于,user对象存放在堆里边,其引用存放在栈里边,其参数传递图如下。
user是对象的引用,为实参,然后创建一个副本temp,把它传递给形参user1。但是,他们实际操作的都是堆内存中的同一个User对象。因此,对象内容的修改也会体现到实参user上。
image
3-传递类型是String类型
public class TestStr {
public static void main(String[] args) {
String str = new String("zhangsan");
System.out.println("字符串修改前:"+str);
changeStr(str);
System.out.println("字符串修改后:"+str);
}
private static void changeStr(String str) {
str = "lisi";
}
}
结果:
字符串修改前:zhangsan
字符串修改后:zhangsan
String也是引用类型,为什么在这又不变了呢?传递参数是引用类型,并不代表就是引用传递,其实它还是值传递。
图中,str是对象 zhangsan的引用,为实参,然后创建了一个副本temp,把它传递给了形参str1。此时,创建了一个新的对象 lisi ,形参str1指向这个对象,但是原来的实参str还是指向zhangsan。因此,形参内容的修改并不会影响到实参内容。
所以,两次打印结果都是zhangsan。
image
总结:
值传递,不论传递的参数类型是值类型还是引用类型,都会在调用栈上创建一个形参的副本。不同的是,对于值类型来说,复制的就是整个原始值的复制。而对于引用类型来说,由于在调用栈中只存储对象的引用,因此复制的只是这个引用,而不是原始对象。
最后,再次强调一下,传递参数是引用类型,或者说是对象时,并不代表它就是引用传递。引用传递不是用来形容参数的类型的,不要被“引用”这个词本身迷惑了。这就如同我们生活中说的地瓜不是瓜,而是红薯一样。
- 参数传递时,是拷贝实参的副本,然后传递给形参。(值传递)
- 在函数中,只有修改了实参所指向的对象内容,才会影响到实参。
猜你喜欢
- 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)
本文暂时没有评论,来添加一个吧(●'◡'●)