使用「;“最后的”;Java中的方法参数

使用「;“最后的”;Java中的方法参数,java,methods,parameters,final,Java,Methods,Parameters,Final,我饶有兴趣地读到这个问题: 结果是参数(不是原语)是通过复制引用值来传递的。 如示例所述;您不能修改您提供的参数的引用: 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 O

我饶有兴趣地读到这个问题:

结果是参数(不是原语)是通过复制引用值来传递的。 如示例所述;您不能修改您提供的参数的引用:

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
放入方法参数


谢谢

我通常这样做是为了防止意外或无意地修改此引用。e、 g

private String doSomething(final String arg) {
   // final to prevent me doing something stupid!
}
一个有趣的场景是setters。您希望确保设置的是成员变量,而不是传入的参数。e、 g

在上面的场景中,如果方法参数是而不是final,那么我可以设置

   arg = arg;

错了。以上是一种常见的打字错误,也可能由于搜索/替换重构而发生。通过将
arg设置为final,您不能意外地重新分配它。

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

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


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

通常不应修改参数,因为这会引入难以发现的错误。但是,也有一些有用的习惯用法和情况可以使用:

public void print(String msg, int count) {
    msg = (msg != null)? msg : "Default";
    while(--count >= 0) {
        System.out.println(msg);
    }
}
为了避免这种情况:

public void searchBiggest(String startingWith) {
    for (String s : collection) {
        if (s.startsWith(startingWith)) {
            startingWith = s;
        }
    }
    return startingWith;
}
正如您所看到的,它使代码变得不直观,因为参数可能包含一个传递的不同值

发件人:

像这样的小虫子通常是最难找到的。通过 墨菲定律,你绝对可以保证这段代码会在 项目的一大块的中间部分,以及错误报告 不会直接把你带到这里。而且,你可能不会注意到 缺陷的影响,直到它进入生产和用户 尖叫着要修理

一旦你写作,你就不能忘记这一点 密码,故事还没有结束。人们将进行更改、添加和修改 代码中的错误。您将必须查看代码并进行修复 一切都搞砸了。以防止出现此问题- 振铃,请执行以下操作:


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

1。当通过调用方法调用对象引用变量时,您正在将该变量作为参数传递。

    mutate(o);
2.通过在方法定义中的
参数
上使用
final
关键字,您已经将其设置为final,因此这意味着局部对象引用变量
o
属于类型的对象是final,因此此变量不能用于指向任何其他对象。

    mutate(o);
注意:它是
对象引用变量
,它是
最终的
不是堆上的对象

mutate(最终对象o)

3。您可以将与对象引用变量o关联的对象分配给其他对象引用变量,然后对其进行更改

Object i = o;
 i = "GoodBye";

避免在方法中使用该参数作为变量,使其易于阅读/理解。在方法中创建匿名内部类时,需要将参数设置为final,以便在匿名类中使用。我同意这一点,但最后,为什么会有人想要更改引用,因为它只能在方法上下文中修改?我已经看到过一些代码,它们使用参数作为变量,它们对参数值做了一些处理,在参数值被重写后,将其用于方法本身,以避免声明新变量的痛苦?这是懒惰,但有时人们做懒惰的事情@布里亚纳涅我会尽我所能去做的。@AljoshaBre-做什么?懒惰的东西?:-)对这是我的标准做法。我现在使用Scala,它默认为这种行为。好的,所以肯定是为了避免在某些情况下创建新变量。要么你对其他开发人员有信心,让他们这样做,要么你强迫他们使用temp变量。谢谢大家,我同意这个答案,因为它更接近“哪里不使用final?”。其他答案给了我
final
的好处,我已经知道了。