不应该指定参数’foo’ – 有什么危害?

比较这种方法:

void doStuff(String val) { if (val == null) { val = DEFAULT_VALUE; } // lots of complex processing on val } 

……对这种方法:

 void doStuff(String origVal) { String val = origVal; if (val == null) { val = DEFAULT_VALUE; } // lots of complex processing on val } 

对于前一种方法,Eclipse会发出警告“不应分配参数’val’”。 为什么?

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

(注意:假设封闭类中没有名为val字段。)

它看起来并不像任何人在这里做出了一个吝啬鬼的案子。

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

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

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

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

我不能在摘要中聪明地谈论你的具体案例,但除了我可能做的所有其他事情,我赞成:

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

或者甚至(假设你不会在只有一个参数的真实方法中处理空值,它必须是更复杂的东西的一部分)…另外,通常,应该明确记录接受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 } 

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

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

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

根据我的经验,使用null作为默认参数的标记是Python中的一个习惯用法。 在Java中,您可以重载该方法。

 void doStuff() { doStuff(DEFAULT_VALUE); } void doStuff(final String val) { assert (val != null); // or whatever ... } 

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

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

替代文字

我怀疑这是一个风格问题 ; 更多的程序员指南而不是实际的潜在问题。 有些人可能会发现处理原始参数值会产生误导。