编程后端开发者

Java中参数传递机制是如何工作的(传值),以及这与其他编程语言有什么不同?

用 Hintsage AI 助手通过面试

答案

在Java中始终使用_传值_(pass-by-value)机制,但对象有一些特别之处:

  • 对于基本类型,复制的是值本身。
  • 对于对象,复制的是对对象的_引用值_,而不是对象本身。

因此,在方法内部修改对象的字段会影响原始对象,而尝试在方法内部将新引用赋值给变量则不会对原始对象产生影响。这常常和传引用(pass-by-reference)混淆,但Java并不支持传引用!

示例:

void changePrimitive(int a) { a = 10; } void changeObject(Point p) { p.x = 10; } int num = 5; changePrimitive(num); // num仍然是5 Point pt = new Point(1, 2); changeObject(pt); // 现在pt.x == 10

重要! 如果在方法内部赋值p = new Point(100, 200),原始对象在方法外是不会改变的。改变的是对象的字段,而不是它的引用!

设置陷阱的问题

问题: 是否可以从方法中更改传递的对象,使得在方法外的引用变量指向新对象?

答案: 不可以。方法内部给参数重新赋值新的引用,仅影响复制的引用,这在方法结束后消失。在方法外,参数变量仍指向原对象。

void reassign(Point p) { p = new Point(100, 200); // 仅在局部有效! } Point pt = new Point(5, 5); reassign(pt); // pt仍然是(5, 5)

由于不了解此主题细微差别而导致的实际错误示例


故事

在一个大型金融系统中实现了一个API,该API通过修改方法内部的引用“返回”对象的更改。结果是方法退出后更改未反映。需要完全重新设计部分逻辑,以清晰区分变异和返回新对象。


故事

在尝试为Java中的两个对象实现交换方法swap(A a, B b)时,开发人员传递了引用并在方法内部交换了它们的位置。这没有成功。要么返回结果,要么使用数组容器。对传值的误解导致了对象交换的不正确。


故事

项目的一位参与者将逻辑从C++迁移过来,期待传引用的行为。结果方法未能正常工作:方法内部的更改未“传出”。急需重新编写关键代码部分,耗费了大量时间。