2

我感兴趣地阅读了这个问题: 我可以在 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隐式或强制的?

我很少将finalJava 中的方法参数用于方法参数,但现在我想不出你会自愿省略放入final方法参数的任何情况。

谢谢!

4

5 回答 5

4

为了避免这种情况:

public void searchBiggest(String startingWith) {
    for (String s : collection) {
        if (s.startsWith(startingWith)) {
            startingWith = s;
        }
    }
    return startingWith;
}

如您所见,它使代码不直观,因为参数可能包含与传递的值不同的值。

来自Hard Core Java - 第 2 章

像这样的小错误通常是最难找到的。根据墨菲定律,你绝对可以保证这段代码会出现在你项目的一大块中间,而且错误报告不会直接把你带到这里。更重要的是,您可能不会注意到错误的影响,直到它投入生产并且用户尖叫着要修复。

你不能忘记,一旦你写了代码,故事还没有结束。人们会在您的代码中进行更改、添加和错误。您将不得不查看代码并修复所有被搞砸的东西。为防止发生此问题,请执行以下操作:

并且使用该参数完成了类似的示例,并使用该参数另外调用其他方法(已更改)。

于 2012-07-31T09:06:14.850 回答
3

通常你不应该修改参数,因为它会引入难以发现的错误。但是,有一些有用的习语和情况可能会很有用:

public void print(String msg, int count) {
    msg = (msg != null)? msg : "Default";
    while(--count >= 0) {
        System.out.println(msg);
    }
}
于 2012-07-31T09:05:01.553 回答
3

我通常这样做是为了防止意外或意外修改此参考。例如

private String doSomething(final String arg) {
   // final to prevent me doing something stupid!
}

一个有趣的场景是在二传手中。您要确保设置成员变量而不是传入的 arg。例如

public void setArg(String arg) {
   _arg = arg;
}

在上述场景中,如果方法参数不是最终的,那么我可以设置

   arg = arg;

因为失误。以上是一个常见的错字,或者可能由于搜索/替换重构而发生。通过制作argfinal,您不会意外地重新分配它。

于 2012-07-31T09:01:26.107 回答
2

1. You are passing the Object Reference Variable as the Argument, when you invoked the method by calling it.

    mutate(o);

2. By using the final keyword on the Parameter in the Method Definition, you have made it final, So it means that local Object Reference Variable o which is of type Object is final, so this variable can't be used to point any other object.

(Note: Its the Object Reference Variable which is final, Not the Object on the HEAP)

mutate(final Object o)

3. You can assign the object associated with the Object Reference Variable o to some other Object Reference Variable and then change it.

Object i = o;
 i = "GoodBye";
于 2012-07-31T09:12:39.440 回答
2

Java 按值传递。因此,当您调用 mutate 时,会传递 o 的副本。

在 mutate 内部,o 的副本然后被设置为指向“再见”。原来的o不变。

将参数设置为 final 不会改变这一点,但正如您所见,它将停止重新分配原始引用的副本。然而,这与停止重新分配原始引用不同。

于 2012-07-31T09:03:52.900 回答