前言

前段时间在群里看到类似这样一个问题,下面的代码会输出什么呢?

public void test() {String str = "hello";change(str);System.out.println(str);
}
private void change(String str) {str = "world";
}

当时看到这题,瞬间勾起了我的回忆。遥想当年,也曾经碰到过类似的问题,当时研究了好久才搞明白,这里再记录一下这个问题的思路。

先来说一下答案:输出:hello

解决这类问题首先要搞明白Java到底是引用传递还是值传递

Java到底是引用传递还是值传递

首先来解释一下什么是引用传递,什么是值传递。

  • 引用传递(pass by reference)是指在调用方法时将实际参数的地址直接传递到方法中,那么在方法中对参数所进行的修改,将影响到实际参数。
  • 值传递(pass by value)是指在调用方法时将实际参数拷贝一份传递到方法中,这样在方法中如果对参数进行修改,将不会影响到实际参数。

那在Java中到底是引用传递还是值传递呢?其实这个问题也一直是争论不断,而且官方也没给个确切答案。但是就我个人理解,Java是值转递

我们先来看一个简单的例子:

public void test() {int a = 1;change(a);System.out.println("a的值:" + a);
}
private void change(int a) {a = a + 1;
}
// 输出
a的值:1

在test()方法中定义了一个基本类型的变量a,然后调用change()方法试图改变这个变量,最后输出的还是原来的值。

首先我们要清楚,一个方法中的局部变量是存在栈中的,如果是基本类型的变量则直接存的是这个变量的值,如果是引用类型的变量则存的是值的地址,指向堆中具体的值。

上面的例子中,调用change()方法传递的a,其实是a变量的拷贝,不是真正的a,在change()方法中改变的是拷贝,对真正的a是没有影响的。

这么一看,Java确实是值传递,但是我们再看下面这个例子,你就会纠结了

public void test() {User user = new User();user.setAge(18);change(user);System.out.println("年龄:" + user.getAge());
}
private void change(User user) {user.setAge(19);
}
// 输出
年龄:19

看,对象里的属性被改变了,不是值传递吗,应该不会改变啊,这时候就有人总结了,当传的值是基本类型时是值传递、当传的是引用类型时是引用传递。真的是这样吗?

分析这个问题,我们需要知道变量在jvm中是怎么存储的。

首先看基本类型,这个很简单,变量在栈中直接存的是值,传到change()方法的是这个变量的拷贝,因此对拷贝的变量修改不会影响原变量的值。

接着看引用类型,变量在栈中存储的是引用地址,这个地址指向堆中具体的值,如下图:

当调用change()方法传入变量时,也是拷贝变量,但是这里的拷贝只是栈中的引用地址,并不会拷贝堆中的数据,因此会变成下图这样:

虽然变量是拷贝,但是指向的地址是同一个,因此对变量中的数据修改时,还是会影响到原来真实的变量,但是,如果我们修改的是变量在栈中的地址,则不会影响原变量,例如下面这段代码:

public void test() {User user = new User();user.setAge(18);change(user);System.out.println("年龄:" + user.getAge());
}
private void change(User user) {user = new User();user.setAge(19);
}
// 输出
年龄:18

这种是修改变量在栈中的地址,则不会影响原变量。

说到这里,大家差不多懂了,但是回头看最开始的那个问题,传入String类型的变量,String是引用类型,按道理,原变量是会被改变的呀,结果怎么是不变呢?

String变量比较特殊,我们看String的源码可以知道,String的值是通过内部的char[]数组来维护的,但是这个数据定义的是final类型的,因此,String的值是不可变的。我们平时修改String的值,其实是重新new了一个String对象,例如下面这段代码:

String a = "hello";
a = "world";

这段代码里,其实a变量并没有被修改成world,只是重新new了一个String对象,这个对象的值是world,并把这个对象的引用地址赋给了a,原来的hello还是在堆中,只是这个值没有被引用,过段时间会被gc垃圾回收。

String变量传值在内存中的变化如下图:

String拷贝的是变量地址,但是它改变不了原String的值,因为String是不可变的,所以在change()方法中是重新new了一个String对象,改变的是新对象的值,原变量是没有影响的。

结论

Java是值传递当传的是基本类型时,传的是值的拷贝,对拷贝变量的修改不影响原变量;当传的是引用类型时,传的是引用地址的拷贝,但是拷贝的地址和真实地址指向的都是同一个真实数据,因此可以修改原变量中的值;当传的是String类型时,虽然拷贝的也是引用地址,指向的是同一个数据,但是String的值不能被修改,因此无法修改原变量中的值。


扫一扫,关注我

Java到底是引用传递还是值传递相关推荐

  1. java int 传引用吗_Java值传递还是引用传递?

    从我实习面试开始就有在面试中遇到过这个问题:Java是值传递还是引用传递? 当时的我只会背背面试题,但是网上的答案有些还是错的,导致我决心写这一篇文章. 虽然网上已经有很多文章珠玉在前,但是我还是想写 ...

  2. java包装和引用_回顾值传递和引用传递关于Java是值传递还是引用传递,网上有不一样的说法。1、基本类型或基本类型的包装类以及String是值传递,引用类型是引用传递。2...

    回顾值传递和引用传递 关于Java是值传递还是引用传递,网上有不一样的说法. 1.基本类型或基本类型的包装类以及String是值传递,引用类型是引用传递. 2.Java中只有值传递. 关于这个问题应该 ...

  3. java还值_Java到底是引用传递还是值传递

    前言 前段时间在群里看到类似这样一个问题,下面的代码会输出什么呢? public void test(){ String str = "hello"; change(str); S ...

  4. java中是引用传递还是值传递....

    刚才与Z师兄聊天,他提问: 你说java中是引用传递还是值传递啊? 当时俺搞混了这个"传递"的意思, 本来以为是对象的实例化比如: abc a=new abc(); 这个a 是引用 ...

  5. java引用传递_理解Java中的引用传递和值传递

    关于Java传参时是引用传递还是值传递,是一个讨论比较多的话题, 有说Java中只有值传递,也有些地方说引用传递和值传递都存在,本篇记录思考过程,不保证正确性, 感兴趣的同学一起讨论. 1.基本类型和 ...

  6. java中的参数传递(只有值传递没有引用传递)

    Java中只有传值调用(值传递),没有传址调用(址传递或者引用传递).所以在java方法中改变参数的值是不会改变原变量的值的,但为什么改变引用变量的属性值却可以呢?请看下面的解答. java中的数据类 ...

  7. java是引用传递还是值传递_流言终结者:Java是引用传递还是值传递?

    前言 今天聊一个很小的话题,引用传递和值传递.为什么拉出这个话题呢?因为自己太菜吧-在这上边栽了跟头.所以今天就聊一聊Java中是引用传递还是值传递. 正文 小A:MDove,我有一个疑问:Java的 ...

  8. Java修炼之路——基础篇——值传递

    什么是值传递?引用传递? 值传递:值传递是将变量的一个副本传递到方法中,方法中如何操作该副本,都不会影响原变量的值.引用传递:引用传递是将变量的地址传递到方法中,方法中操作该变量,会对其产生影响. 为 ...

  9. Java基础篇:什么是值传递

    Java类的结构的内存解析 内存分为4部分:栈.堆.方法区.静态域 栈:对象的引用名,数组的引用名,局部变量(方法的形参,方法内定义的变量,代码块中定义的变量) 堆:new 出来的"东西&q ...

最新文章

  1. 20161124网络爬虫技术学习
  2. 【topoSort拓扑排序】1424. 奖金(简单题目看拓扑排序)
  3. 概率分布的熵归一化(Entropy Normalization)
  4. python udp编程_在Python下进行UDP网络编程的教程
  5. MacOS上的包管理工具
  6. windows和linux下的spice客户端使用方法
  7. 一个好端端的团队是如何被管理者搞垮的?
  8. 串口调试工具 minicom使用教程
  9. 共享计算机怎么连,电脑如何连接共享文件
  10. 什么是存储器?存储器可分为哪三类?
  11. JavaScript实现输入框(密码框)出现提示语
  12. 如何搞懂html+php实现个人博客网站?【附代码详解】毕业设计 大作业项目
  13. 博士申请 | 香港城市大学刘晨老师组招收机器学习方向全奖博士/博后/硕士/RA...
  14. ssh-keygen认证密钥
  15. 分奖金(python)
  16. [思语]_我心中的大师
  17. PS中的cs3版本也有调整边缘的功能
  18. 万维网、因特网和互联网的区别
  19. Berkeley DB JE 学习笔记
  20. 微信小程序【DEMO】:会议室预定小程序

热门文章

  1. java 根据时区算出这个时区的时间
  2. CMMI软件开发过程及能力成熟度模型评估
  3. Firefox未通过针对是否适用于Firefox的验证,现已被禁用的解决方案
  4. 【Google 搜索】Google 搜索技巧 2019_12_30
  5. 2020:下一个十年,存储发展的趋势是什么?(全集)
  6. 我的世界光影mod怎么用_大片的正确打开方式-MineCraft光影材质包安装及使用教程...
  7. origin绘图软件安装包下载安装,Origin软件2022版特色功能使用
  8. 中软实习培训记录二(0721)
  9. AUTOSAR PN网络管理测试开发实践
  10. “WindowBuilder was not able to show the GUI“报错解决