我感兴趣地阅读了这个问题: Can I pass parameters by reference in Java?
通过复制参考值传递参数(不是基元)。 因此,例子说明;你不能修改你给出的参数的参考:
Object o = "Hello";
mutate(o)
System.out.println(o); // Will print Hello
private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!
使用final
这样的问题可以避免这种问题:
private void mutate(final Object o) { o = "Goodbye"; } //Compilation error
问题:
final
关键字是否仅用于抛出编译错误? final
不是隐式或强制的?我很少在Java中使用final
作为方法参数,但现在我无法想到你会自愿省略将final
放入方法参数的任何情况。
谢谢!
答案 0 :(得分:4)
为避免这种情况:
public void searchBiggest(String startingWith) {
for (String s : collection) {
if (s.startsWith(startingWith)) {
startingWith = s;
}
}
return startingWith;
}
正如您所看到的,它使代码不直观,因为参数可能保持与传递的值不同的值。
像这样的小虫子往往是最难找到的。通过 墨菲定律,你绝对可以保证这段代码会在 项目的一大块中间,错误报告 不会直接带你到这里。更重要的是,你可能不会注意到 bug直到它投入生产和用户的影响 尖叫着修复。一旦你写作,你就不能忘记 代码,故事还没有结束。人们会做出改变,补充和改变 代码中的错误。您将不得不查看代码并修复 一切都搞砸了。为防止此问题发生 - 戒指,请执行以下操作:
并使用参数完成类似的示例,并使用参数(已更改)另外调用其他方法。
答案 1 :(得分:3)
我通常这样做是为了防止此引用的意外或意外修改。例如
private String doSomething(final String arg) {
// final to prevent me doing something stupid!
}
一个有趣的场景是制定者。您希望确保设置成员变量而不是中传递的arg。 e.g。
public void setArg(String arg) {
_arg = arg;
}
在上面的场景中,如果方法参数不是 final,那么我可以设置
arg = arg;
错误。以上是一个常见的拼写错误,或者可能由于搜索/替换重构而发生。通过arg
最终,您不会意外地重新分配它。
答案 2 :(得分:3)
通常,您不应修改参数,因为它可能会导致很难找到错误。然而,有一些有用的习语和情况可能有用:
public void print(String msg, int count) {
msg = (msg != null)? msg : "Default";
while(--count >= 0) {
System.out.println(msg);
}
}
答案 3 :(得分:2)
Java按值传递。因此,当您调用mutate时,会传递o的副本。
在mutate中,然后将o的副本设置为指向“Goodbye”。原来的o没有变化。
将参数设置为final将不会更改此值,但正如您所见,它将停止重新分配原始引用的副本。然而,这不同于停止重新分配原始参考文献。
答案 4 :(得分:2)
1。当您通过调用方法调用该方法时,您将Object Reference Variable
作为参数传递。
mutate(o);
2。在方法定义中使用final
上的Parameter
关键字,使其成为最终,这意味着本地对象参考变量 o
类型的对象是最终的,因此此变量不能用于指向任何其他对象。强>
(注意:其Object Reference Variable
是final
,不是HEAP上的对象)
mutate(final Object o)
3. 您可以将与对象引用变量o关联的对象分配给其他对象引用变量,然后进行更改。
Object i = o;
i = "GoodBye";