比较这种方法:
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
的字段。)
答案 0 :(得分:35)
这看起来并不像任何人在这里做了一个curmudgeon的案子。
我通常不会改变参数,事实上我倾向于标记我的参数final
以明确禁止它。原因如下:
对参数的分配可能与尝试将其用作“输出参数”混淆,参考:javapractices.com,清晰度就是一切
< / LI>偏好不变性,这与参数值一样多。基元只是同一事物的退化情况,它(通常)更容易推理不可变变量。参考,Effective Java Item 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
}
或者甚至(假设你不会在只有一个参数的实际方法中处理空值,它必须是更复杂的一部分的一部分)...另外,通常,接受null
的方法作为一个参数应该明确记录为这样做,如果只是为了强化空参数应该是例外的假设。在第二种方法中,您甚至可以使用@NonNull
annotation。
/**
* @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上的相关问题(和相关参数):"Using final modifier whenever applicable in Java...","final keyword in method parameters","Do you final-ize local variables and method parameters in Java"。
答案 1 :(得分:14)
在方法中重新分配参数有时被认为是一种不好的做法。它可能来自C / C ++,在方法完成后调用doSomething(myVar)
可以更改myVar
。但对于Java来说情况并非如此。
恕我直言,如果你在方法中做的第一件事,这是完全没问题的。阅读代码的每个人都将了解正在发生的事情。但是,如果深埋在代码中,可能会让人感到困惑。
答案 2 :(得分:7)
根据我的经验,使用null
作为默认参数的标记是Python中的一个习惯用法。在Java中,您可以重载该方法。
void doStuff() {
doStuff(DEFAULT_VALUE);
}
void doStuff(final String val) {
assert (val != null); // or whatever
...
}
答案 3 :(得分:6)
有一个编译器首选项,它指示是否忽略参数赋值实例,标记警告或标记错误。
进入菜单栏 - 选择Window..Preferences,然后 在Preferences对话框的树控件中,选择Java..Compiler..Errors / Warnings,然后选择 在“代码样式”部分中查找“参数分配”设置。
答案 4 :(得分:1)
我怀疑它是style issue;更多的程序员指南而不是实际的潜在问题。有些人可能会发现处理原始参数值会产生误导。