一道笔试题来理顺Java中的值传递和引用传递
前段时间参加了一场面试,其中有一道引用传递的题,因为当时并没有考虑清楚所以做错了。
现在来复盘一下,题目如下:
private static void change(StringBuffer str11, StringBuffer str12) {
str12 = str11;
str11 = new StringBuffer("new world");
str12.append("new world");
}
public static void main(String[] args) {
StringBuffer str1 = new StringBuffer("good ");
StringBuffer str2 = new StringBuffer("bad ");
change(str1, str2);
System.out.println(str1.toString());
System.out.println(str2.toString());
}
good new
world
bad
下面就来复盘一下为何是这两个答案,下面会做详细的图文分析。
要搞明白这个问题,那么就需要明白Java中的值传递和引用传递了。
Java对象参数传递虽然传递的是地址(引用),但仍然是值调用。是时候需要给引用调用和值调用一个准确的定义了。
-
值调用(call by value): 在参数传递过程中,形参和实参占用了两个完全不同的内存空间。形参所存储的内容是实参存储内容的一份拷贝。实际上,Java对象的传递就符合这个定义,只不过形参和实参所储存的内容并不是常规意义上的变量值,而是变量的地址。咳,回过头想想:变量的地址不也是一种值吗!
-
引用调用(call by reference) : 在参数传递的过程中,形参和实参完全是同一块内存空间,两者不分彼此。 实际上,形参名和实参名只是编程中的不同符号,在程序运行过程中,内存中存储的空间才是最重要的。不同的变量名并不能说明占用的内存存储空间不同。
那么接下来就画图分析文章开头抛出的问题:
这里再把代码贴一遍,大家可以对比着代码和图一起看。
private static void change(StringBuffer str11, StringBuffer str12) {
str12 = str11;//2
str11 = new StringBuffer("new world");//3
str12.append("new world");//4
}//5
public static void main(String[] args) {
StringBuffer str1 = new StringBuffer("good ");
StringBuffer str2 = new StringBuffer("bad ");
change(str1, str2);//1
System.out.println(str1.toString());
System.out.println(str2.toString());
}
-
执行到第一步的图:
-
执行到第二步的图,这里chage方法中的形参str11,str22是实参str1,str2的地址拷贝。
-
这里str11和str22是实参str1,str2的地址拷贝,接着执行第三步的图:
-
上图中str12地址指向了“good”,接着看第四步图:
-
上图中str11的地址指向了堆中新的对象"new world",接着看第五步的图:
这里图算是画完了,确实不太擅长画图,大家就先勉强看吧。
这里有一个很重要的点就是StringBuffer是可变的,具体解释大家可以搜索下。
因为这里str12.append("new world")直接修改了good的值。所以main函数中打印的会是:good new world。
到这里就算讲完了,一个很简单的例子,这里算是对之前一道笔试题的复盘,有不对的地方欢迎大家指正。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?