Java 如果(x!=y)vs如果(x==y)

Java 如果(x!=y)vs如果(x==y),java,eclipse,pmd,Java,Eclipse,Pmd,我已经针对我的代码在Eclipse中运行了,我得到了一个类似于下面所示的代码的高优先级警告: if(singleRequest !=null){ // do my work }else{ // do my other work } PMD说`避免if(x!=y)。。;其他.. 错误的描述如下所示: In an "if" expression with an "else" clause, avoid negation in the test. For example, rep

我已经针对我的代码在Eclipse中运行了,我得到了一个类似于下面所示的代码的高优先级警告:

 if(singleRequest !=null){
   // do my work
 }else{
   // do my other work
 }
PMD说
`避免if(x!=y)。。;其他..

错误的描述如下所示:

In an "if" expression with an "else" clause, avoid negation in
the test.  For example, rephrase:
if (x != y) diff(); else same();
as:
if (x == y) same(); else diff();
Most "if (x != y)" cases without an "else" are often return

但我仍然无法理解对代码的影响。如果有人能给我举个例子,我将不胜感激

这是一个可读性问题。考虑

if ( x != y ) 
{
}
else  // "if x doesn't not equal y"
{
}
vs

后一个例子更容易识别。请注意,我看不出用底片有什么错。。。想想看,这会更有意义

if ( x != null )...
您必须避免在if条件中出现“不相等”。这是因为当其他人查看您的代码时,该人很可能会忽略!=可能会对程序的逻辑得出错误的结论


对于您的情况,您可能需要将if逻辑与else逻辑交换并更改!=to=

这是代码可读性与代码组织之间的平衡。这个警告基本上是在暗示阅读代码的人在否定词的否定词中导航是令人困惑的

我个人的经验法则是,无论你期望“正常”的情况是什么,你都应该在if中进行测试。考虑:

 if (x != y) {
   // do work here...
 } else {
   throw new IllegalArgumentException();
 }
在这种情况下,我认为重要的工作是在
x!=y
case,这就是您应该测试的内容。这是因为我喜欢组织代码,使重要的工作排在第一位,然后处理异常情况。

这是因为“良好风格”表示,如果可能,测试应该是“积极的”,因此:

更容易阅读,因为测试是“肯定的”(即“等于”而不是“不等于”),最终更好的可读性导致更少的错误

编辑 这在测试中尤其如此,例如:

if (!str.equals("foo")) {
您很容易错过
在前面,但是如果你让测试呈阳性,它会干净得多


只有在没有
else
块的情况下,才应该进行否定测试-那么否定测试是不可避免的,除非你有一个空的
true
块,这本身被认为是一个风格问题。

我避免使用否定格的唯一原因是如果它导致了双重否定,这可能会让人困惑

e、 g


PMD是一种工具。PMD基于启发式工作。有人决定了这个启发;带有else语句的否定条件句不是“好的风格”

然而,在这种情况下,正如我在评论中所指出的,发布的代码是我将如何编写它。(特别是对于
x!=null
,但不限于此构造。)

这是因为我不看条件(可以简化的除外;例如,去除Jim Kin所示的双重否定),而是看分支或“流”的逻辑

也就是说,我首先放置正分支。在这种情况下,我主张

if (x != null) {
  doValid         // positive branch
} else {
  doFallback
}
在语义上等同于

if (isValid(x)) { // it looks like a "positive conditional" now
  doValid         // still positive branch
} else {
  doFallback
}
因此首先是正分支

当然,并非所有情况下都有如此“清晰”的正向流动,有些表达可能更容易以负面方式表达。在这些情况下,我将“反转”分支-类似于PMD的建议-通常在块的顶部添加注释,说明如果正分支/流被反转时的操作

另一个可能影响所用条件选择的因素是“立即范围退出”分支,如:

if (x == null) {
  // return, break, or
  throw new Exception("oops!");
} else {
  // But in this case, the else is silly
  // and should be removed for clarity (IMOHO) which,
  // if done, avoids the PMD warning entirely
} 

这就是I如何始终如一地(除了一些偶尔的异常)编写代码:
if(x!=null){..}
。使用可用的工具;让他们为你工作。请参阅Steven的答案,了解如何将PMD配置为更合适的“口味”。

谁读取您的代码?是的。编译器是这样做的。或者是讲师的助手。一个无法区分==和!=的同事?希望不是

我只能认为否定在复杂的表达中是不好的。(上下文是:至少对我来说。我知道我在(!expr&&!expr2 | | expr3){}
的时候在头脑中调试时感到沮丧。)

ch=getch();if(ch!='a')
是一种易于扩展到
if(ch!='a'| ch!='b')
这总是正确的,虽然听起来语义正确

从性能的角度来看,最好对概率进行排序

if (more_probable) {
      ....
      unconditional_jump_to_end_of_block;
} else {
   ...
}
这种选择将导致更好的性能,因为在更可能的分支中没有错误预测惩罚


if(p&&p->next)
从性能角度评估的结果很差。

许多PMD规则更多的是风格观点,而不是正确性警报。如果你不同意这个规则或者规则与你的项目的编码标准不匹配,你可以考虑甚至是

不是一个答案,但是你可以通过返回或失败早而不缩进来最小化整体的复杂性和提高可读性:

if (something == null) {
    throw new IllegalArgumentException("something must not be null");
}

// continue here

这不仅仅是插件对代码结构的教条吗?它是“建议”避免负面情况。我认为在这种情况下这是垃圾,因为“消极条件”实际上导致了“积极情况”。你的代码很好。它并不总是一个可读性问题。。。关于可读性标准,最重要的是知道什么时候应该忽略关于它们的警告,因为代码实际上更易于阅读。如果你认为你的逻辑对你更有意义,就不要写。运营商存在是有原因的,如果是这样的话,就不会有运营商了!=操作人员请记住,这些风格的模块是由那些风格各异的人编写的,因为它们是,并且他们经常代表他们的观点是任意的。我已经看到了关于C++编程的建议,通常是因为= =和!=!可以在类上重写运算符,并且!=运算符通常只调用==运算符并对结果求反,因此代码最终是两次跳转
if (x == null) {
  // return, break, or
  throw new Exception("oops!");
} else {
  // But in this case, the else is silly
  // and should be removed for clarity (IMOHO) which,
  // if done, avoids the PMD warning entirely
} 
if (more_probable) {
      ....
      unconditional_jump_to_end_of_block;
} else {
   ...
}
if (something == null) {
    throw new IllegalArgumentException("something must not be null");
}

// continue here