不应该指定参数'foo' - 有什么危害?

Mat*_*nry 29 java eclipse warnings compiler-warnings

比较这种方法:

void doStuff(String val) {
    if (val == null) {
        val = DEFAULT_VALUE;
    }

    // lots of complex processing on val
}
Run Code Online (Sandbox Code Playgroud)

...对于这种方法:

void doStuff(String origVal) {
    String val = origVal;
    if (val == null) {
        val = DEFAULT_VALUE;
    }

    // lots of complex processing on val
}
Run Code Online (Sandbox Code Playgroud)

对于前一种方法,Eclipse会发出警告"不应分配参数'val'".为什么?

在我看来,前者更清洁.首先,它并没有迫使我想出两个好名字val(想出一个好的名字就足够了).

(注意:假设val封闭类中没有命名的字段.)

and*_*soj 35

它看起来并不像任何人在这里做了一个curmudgeon的案子.

我通常不会改变参数,事实上我倾向于标记我的参数final以明确禁止它.原因如下:

  • 对参数的赋值可能会与尝试将其用作"输出参数"混淆,参考:javapractices.com,清晰度就是一切

  • 偏爱不变性,这与参数值一样多.基元只是同一事物的退化情况,它(通常)更容易推理不可变变量.参考,有效Java项目13,或javapractices.com

  • 最后(NPI),使用最终自由,javapractices.com.不管它有多丑,它可能在参数签名中,我相信它倾向于识别意外错误,并突出显示可变变量,这通常应该是例外.大多数代码中的大多数可变变量都存在于懒惰或感知它对性能有一定影响,当明智地选择,不可变,以及命名良好的中间计算更清晰,更易于阅读和验证,并且可以针对性能进行干净优化没有你的帮助.

我不能巧妙地对你的具体案例说清楚,但除了我可能做的所有其他事情,我赞成:

void doStuff(final String origVal)
{
    final String valOrDefault = (origVal == null) ? DEFAULT_VALUE : origVal;
    //lots of complex processing on valOrDefault 
}
Run Code Online (Sandbox Code Playgroud)

或者甚至(假设你不会在只有一个参数的真实方法中处理空值,它必须是更复杂的一部分)...另外,通常,null作为参数接受的方法应该明确记录为这样做,如果只是为了强化空参数应该是例外的假设.在第二种方法中,您甚至可以使用@NonNull注释.

/**
  * @param origVal string giving value, possibly null, in which case DEFAULT_VALUE is assigned
  */
void doStuff(final String origVal, ... )
{
    final String valOrDefault = (origVal == null) ? DEFAULT_VALUE : origVal; 
    // similar mucking about to make all the parameters behave, separate from
    // actually operating on them...
    ...
    reallyDoStuff(valOrDefault,...);
}

private void reallyDoStuff(final String value, ...)
{
   assert (value != null);
   // do your complex processing
}
Run Code Online (Sandbox Code Playgroud)

StackOverflow上的相关问题(和相关参数): "在Java中适用时使用最终修饰符......","方法参数中的最终关键字","您是否在Java中最终使用局部变量和方法参数".

  • 我不明白最终和输出参数有什么关系.最终参数仍然是可变的,可以用作输出参数.另一方面,final禁止为参数分配新对象,并确保存在对原始对象的引用,因此可以将其用于输出.我认为final并没有强调参数不是输出参数.事实上,情况恰恰相反.我错了吗? (4认同)
  • 我的2美分:java中没有out参数!任何对它感到困惑的人都应该回到学校.由于java中没有默认参数,我检查为null,如果是这种情况,我会将默认值分配给参数本身.(我知道你可以重载方法,但有些情况你需要这个 - 例如spring mvc) (3认同)
  • 一个downvote?谁知道?;-)你不喜欢什么? (2认同)

Nik*_*bak 14

在方法中重新分配参数有时被认为是一种不好的做法.它可能来自C/C++,其中调用doSomething(myVar)可以myVar在方法完成后改变.但Java并非如此.

恕我直言,如果你作为方法的第一件事,这是完全没问题.阅读代码的每个人都将了解正在发生的事情.但是,如果深埋在代码中,可能会让人感到困惑.


Jos*_*Lee 7

根据我的经验,使用null默认参数的哨兵更像是Python中的习惯用语.在Java中,您可以重载该方法.

void doStuff() {
    doStuff(DEFAULT_VALUE);
}

void doStuff(final String val) {
    assert (val != null); // or whatever
    ...
}
Run Code Online (Sandbox Code Playgroud)


Lad*_*ein 6

有一个编译器首选项,它指示是否忽略参数赋值实例,标记警告或标记错误.

转到菜单栏 - 选择Window..Preferences,然后在Preferences对话框的树形控件中,选择Java..Compiler..Errors/Warnings,然后在Code Style部分查找"Parameter Assignment"设置.

替代文字