文章目录
54. Java 类和对象 - 传递引用数据类型参数
在 Java 中,引用类型(如对象或数组)作为参数传递时,采用的也是**值传递(pass-by-value)**机制!不过这里要特别注意的是:
- ✅ 引用的复制:传递的是对象的引用副本,而不是对象本身。
- ✅ 影响对象状态:如果你通过引用修改对象的属性(字段),这些更改会影响原对象,因为引用指向的是同一个对象。
- ✅ 重新赋值引用:如果你在方法里让引用指向另一个对象,这种改变不会影响外部的引用。
🌟 1. 示例:moveCircle 方法
来看个例子:
public void moveCircle(Circle circle, int deltaX, int deltaY) {
// ✅ 改变 circle 引用指向对象的状态
circle.setX(circle.getX() + deltaX);
circle.setY(circle.getY() + deltaY);
// 🚨 将 circle 引用重新指向一个新的 Circle 对象
circle = new Circle(0, 0);
}
🎯 1.1 改变对象属性
circle.setX(circle.getX() + deltaX);
circle.setY(circle.getY() + deltaY);
- circle 是引用的副本:它指向同一个 Circle 对象。
- ✅ 更改对象的状态:通过
setX()和setY()修改的是对象本身的字段,因此这些更改在方法外部依然生效。
🚨 1.2 重新赋值引用
circle = new Circle(0, 0);
- 这行代码让
circle重新指向 一个新对象(0, 0)。 - 影响范围:只在当前方法内部生效!外部的
myCircle不会受影响,因为它指向的还是最初的对象。
📞 2. 调用方法示例
Circle myCircle = new Circle(10, 15); // 初始坐标 (10, 15)
moveCircle(myCircle, 23, 56);
System.out.println("After moveCircle: x = " + myCircle.getX() + ", y = " + myCircle.getY());
执行逻辑:
- 初始状态:
myCircle.x = 10,myCircle.y = 15 - 调用
moveCircle(myCircle, 23, 56)后:- ✅ 坐标更新:
myCircle.x = 10 + 23 = 33 - ✅ 坐标更新:
myCircle.y = 15 + 56 = 71 - 🚨 引用重新赋值:方法内部的
circle指向新对象(0, 0),但这不会影响外部的myCircle
- ✅ 坐标更新:
- 方法结束:
myCircle仍指向原对象(33, 71)
输出结果:
After moveCircle: x = 33, y = 71
🏁 3. 理解机制:值传递 vs. 引用的可变性
Java 的引用类型参数机制可以这样理解:
- ✅ 值传递:无论基元类型还是引用类型,
Java传递的都是值。引用类型传递的是对象引用的副本。 - ✅ 对象可变性:通过引用修改对象的字段会影响外部对象,因为两者指向的是同一个内存地址。
- ✅ 重新赋值引用:仅在方法内部生效,不会影响方法外的引用。
📚 4. 小结
🌟 一句话记忆:Java 总是值传递!
- 基元类型:传递的是值本身。
- 引用类型:传递的是引用的值(对象地址的副本)。
- ✅ 修改对象字段 = 影响原对象
- 🚨 重新赋值引用 = 只影响方法内的副本,不改变外部引用
理解这点,能够帮你避免在方法中误以为重新赋值引用就会改变外部对象的问题,也让你在编写代码时更清晰地掌握对象和引用的关系。💡
🎯 思考题
你觉得下面这段代码输出的是什么?为什么?
public class Test {
public static void main(String[] args) {
String s = "Hello";
changeString(s);
System.out.println(s);
}
public static void changeString(String str) {
str = "World";
}
}
👉 答案可以在下节课揭晓,也欢迎大家讨论你的理解!🔥
🎯 思考题解析
在 Java 中,字符串 (String) 是 不可变对象(Immutable)。当你在 changeString 方法中执行 str = "World";,实际上是让 str 指向了一个新的字符串对象,但这不会影响 main 方法中原来的 s 变量。
🚀 关键点:
String在 Java 中是 不可变的,任何修改都会生成一个新的String对象,而不会影响原来的对象。Java方法传递的是参数的副本,这里传递的是s的引用的副本,而str = "World";只是改变了str的指向,并未修改s指向的内容。
🔍 输出结果:
Hello
👉 思考延伸:
如果想要修改 String 的内容,该怎么办?有什么数据类型是可变的?欢迎大家讨论!🔥
👉 思考延伸解析:
在 Java 中,String 是 不可变(Immutable) 的,所以无法直接修改它的内容。那么如果我们想要修改字符串,该怎么办呢?
✅ 解决方案 1:使用 StringBuilder 或 StringBuffer(可变字符串)
StringBuilder 和 StringBuffer 提供了 可变字符串,允许我们在原有字符串上进行修改,而不会创建新的对象。
🔹 示例代码:
java复制编辑public class Test {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello");
changeString(sb);
System.out.println(sb);
}
public static void changeString(StringBuilder str) {
str.append(" World");
}
}
🔹 输出结果:
Hello World
🎯 为什么这样就能修改呢?
因为 StringBuilder 是可变对象,str.append(" World") 修改了同一个对象的内容,所以 main 方法中的 sb 也受到了影响。
✅ 解决方案 2:用 String 手动返回新值
如果仍想用 String,可以返回修改后的新值。
🔹 示例代码:
public class Test {
public static void main(String[] args) {
String s = "Hello";
s = changeString(s);
System.out.println(s);
}
public static String changeString(String str) {
return str + " World";
}
}
🔹 输出结果:
Hello World
🎯 为什么这样可以?
因为 String 是不可变的,所以我们需要手动接收返回的新字符串,否则原来的 s 不会改变。
🔥 总结:
如果想要修改字符串的内容: 1️⃣ 使用 StringBuilder / StringBuffer(推荐) —— 适用于频繁修改字符串的场景,避免创建大量 String 对象,提升性能。
2️⃣ 用 String 返回新值 —— 适用于方法内部修改字符串后,返回新字符串给调用者。

被折叠的 条评论
为什么被折叠?



