Java 常见面试题 :聊聊java代码中的值传递、引用传递区别
聊聊java代码中的值传递、引用传递区别是一道Java 常见面试题 ,值传递和引用传递是很基础却又容易让人迷糊的知识点。不少小伙伴虽然会在代码里用,但对它们的原理却一知半解。今天咱就好好唠唠这俩概念,帮大家彻底搞清楚。
引用传递:就像用快捷方式访问资源
在Java里,引用传递的场景很常见。比如说,在一个方法里调用另一个方法,传递的参数是数组,当在子方法里对这个数组进行增加或删除元素的操作时,原方法里的数组也会跟着改变。这是为啥呢?其实啊,数组传递给子方法时,传递的并不是数组本身,而是数组对象的引用。打个比方,这个引用就好比电脑桌面上创建的快捷方式,通过它可以访问到硬盘(比如D盘)里的某个资源,而真正的资源(数组对象)存放在堆内存中。
咱用代码详细解释一下。看下面这段代码:
// 创建一个Integer对象,值为1 Integer a = 1;
在Java虚拟机(JVM)中,会在堆内存里创建一个值为1的Integer
对象。与此同时,在堆栈中会创建一个变量a
,这个a
就是一种引用,它指向堆内存里值为1的Integer
对象,就好像给这个对象贴上了一个标签。
// 创建另一个Integer对象b,并将a的值赋给b Integer b = a;
当执行这行代码时,在堆栈中又创建了一个变量b
,b
同样指向堆内存中值为1的那个Integer
对象,和a
的指向是一样的。这时候,如果对b
进行修改:
// 修改b的值 b = 2;
实际上修改的是堆内存中那个Integer
对象的值。因为a
和b
指向同一个对象,所以a
的值也会跟着变动(这里要注意,在Java中Integer
是不可变类,这里修改b
其实是让b
指向了一个新的Integer
对象,不过为了便于理解引用传递原理,先按上述逻辑理解 )。
不仅是Integer
对象,像数组、集合以及自定义的类,在变量赋值的时候,都属于引用传递。这些变量保存的只是对象在堆内存中的地址,不管通过哪个变量去操作,实际修改的都是堆内存里的同一个对象。
值传递:基础数据类型的“专属”传递方式
说完引用传递,再来讲讲值传递。值传递主要针对Java中的基础数据类型,像int
、char
、float
、double
等。和引用传递不同,基础数据类型的变量及其值是存储在堆栈中的,而不是堆内存。
咱还是用代码来说明:
// 创建一个int类型的变量a,值为1 int a = 1;
这里的a
和值1都存放在堆栈中。
// 创建另一个int类型的变量b,并将a的值赋给b int b = a;
执行这行代码后,相当于在堆栈中重新拷贝了一份a
的值给b
。后续对b
进行修改:
// 修改b的值 b = 2;
此时,b
的值变了,但a
的值并不会受到影响,依然是1。这就是典型的值传递,每个变量都有自己独立的存储空间,修改一个变量不会影响到另一个。
String类型:看似引用传递,实则值传递
这里有个特殊情况要注意,就是String
类型。String
不属于Java的基本数据类型,从使用方式上看,它好像和Integer
等引用类型差不多,很多人会误以为它是引用传递。但实际上,String
是值传递。
这是因为String
类是用final
修饰的,意味着它的值一旦创建就不能被修改。如果对String
变量进行重新赋值,比如:
// 创建一个String类型的变量str,值为"hello" String str = "hello"; // 重新给str赋值 str = "world";
这里并不是修改了原来"hello"
这个字符串的值,而是重新创建了一个"world"
字符串对象,然后让str
指向这个新对象。所以,String
类型在传递和赋值时,遵循的值传递的规则。
到这儿,Java里的值传递和引用传递就讲得差不多了。要是你对今天讲的内容还有啥疑问,欢迎在评论区留言,大家一起讨论讨论!