java中int和string传参均不改变原变量,因java全按值传递:int传值拷贝,string虽为引用类型但不可变,任何“修改”都生成新对象。

Java里int和String传参时,到底改不改得到原变量
Java全是按值传递,没有例外。所谓“对象传引用”是常见误解——实际上传的是引用的副本,不是引用本身。
关键看操作目标:如果方法里重新赋值obj = new Object(),不影响外部;但如果调用obj.setName("x"),外部能看见变化,因为两个引用指向同一块堆内存。
-
int、double等基本类型:传的是值的拷贝,方法内修改完全不影响原变量 -
String:虽是引用类型,但不可变,任何“修改”(如str.concat())都会生成新对象,原引用不变 -
ArrayList、自定义类实例:传的是引用值的拷贝,所以能通过它修改对象状态,但不能让外部变量指向新对象
为什么swap(int a, int b)永远交换不了外面的变量
因为参数a和b只是外部变量值的独立副本,函数内交换它们,就像在复印纸上画箭头改来改去,原件毫发无损。
常见错误是以为写个swap(MyObj x, MyObj y)就能交换对象引用——其实也只是交换了两个副本,外部变量仍指着原来的地址。
立即学习“Java免费学习笔记(深入)”;
- 真要交换两个变量,必须由调用方自己处理(比如放进数组或包装类)
- Java没有指针,也没有类似C++的
&引用参数语法 - 别被IDE调试器里“Variables”视图迷惑:它显示的是当前栈帧里的局部变量,不是原始位置
Integer和int作为参数时,行为差异在哪
表面看都是数字,但Integer是对象,int是基本类型,传参机制相同(都按值),但自动装箱/拆箱会掩盖本质。
比如void inc(Integer i) { i++; },看似在改对象,实则触发拆箱→加1→再装箱,最终赋给局部变量i,外部Integer引用没变,且可能因缓存(-128~127)复用对象而产生误判。
-
Integer传参后做++或=赋值,不会影响外部变量 - 用
Objects.equals(a, b)比较Integer,比a == b安全,避免空指针和缓存陷阱 - 性能上,频繁装箱/拆箱在循环里会明显拖慢,优先用
int做计算
调试时怎么看清楚引用和值的实际关系
别只盯着变量名,重点看三件事:变量存在哪(栈?堆?常量池?)、它当前值是什么(地址?数字?null?)、这个值是否被其他变量共享。
IntelliJ 或 VS Code 调试时,右键变量选 “View as Object” 或展开“Reference Chain”,能直观看到堆中对象被几个栈变量引用。对new String("abc")这种,还会发现字符串内容在堆,而字面量"abc"在字符串常量池。
- 用
System.identityHashCode(obj)可判断两个引用是否指向同一对象(比==更明确) -
String.valueOf(obj)或Objects.toString(obj)比直接obj.toString()防空指针 - 静态分析工具(如SpotBugs)能标出“可疑的未使用返回值”或“忽略装箱开销”,比肉眼靠谱
get()之后的隐式对象创建——它们悄悄改变了引用关系,却不在你写的=符号附近。









