Java if和if-else之间有什么明显的区别吗?

Java if和if-else之间有什么明显的区别吗?,java,coding-style,maintainability,Java,Coding Style,Maintainability,给出以下代码片段,有什么明显的区别吗 public boolean foo(int input) { if(input > 10) { doStuff(); return true; } if(input == 0) { doOtherStuff(); return true; } return false; } vs 或者单出口原则在这段代码中会更好 public boolean foo(int i

给出以下代码片段,有什么明显的区别吗

public boolean foo(int input) {
   if(input > 10) {
       doStuff();
       return true;
   }
   if(input == 0) {
       doOtherStuff();
       return true;
   }

   return false;
}
vs

或者单出口原则在这段代码中会更好

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

是否存在明显的性能差异?您是否觉得其中一个版本比其他版本更易于维护/可读

使用最能描述您意图的任何形式


但是,如果事情这么简单,就不要遵循单出口原则——这只会使它更加混乱。

语义上-否。从性能上看,这取决于编译器,即它是否能够发现这两个条件不能同时为真。我敢打赌标准Sun编译器可以。是否使用单出口原则取决于口味。我个人讨厌它。

第一个片段和第二个片段之间真的没有区别。然而,第三个代码片段效率很低。因为您等待将程序的控制权返回给调用方,直到方法中的最后一行代码,您浪费了处理能力/内存,而前两个代码段在确定其中一个条件为真时立即返回控制。

对于第二个示例,您非常清楚地指出这两个条件是相互排斥的。
对于第一个ifs,则不太清楚,如果(不太可能)在两个ifs之间添加了对
输入的赋值,则逻辑将发生变化。
假设将来有人在第二个if之前添加
input=0

当然,这不太可能发生,但是如果我们在这里讨论可维护性,if-else清楚地说存在相互排斥的条件,而一堆if不存在,它们之间不像if-else块那样相互依赖

编辑:现在我看到了,在这个特定的例子中,return子句强制相互排斥,但我们再次讨论的是可维护性和可读性

无论如何,关于性能,如果这是用Java编写的,那么你不应该关心几个if块的性能,如果它是嵌入在速度非常慢的硬件中的C,也许,但肯定不是用Java编写的。

版本1和版本2可能比版本3快,但我认为性能差异很小。我宁愿关注可读性


就我个人而言,我永远不会使用版本2。在#1和#3之间,我会选择一个为所讨论的案例生成可读性最高的代码。我不喜欢我的方法中有很多退出点,因为这使得代码很难分析。但是,在某些情况下,当我们针对某些特殊情况立即退出时,流程会变得更清晰,并继续处理主要情况。

想想这两个例子不相似时的情况:

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        }
        System.out.println("do some other intermediary stuff");
        if (input == 0) {
            // doOtherStuff();
            return true;
        }

        return false;
    }
vs。 第一种方法可能更灵活,但两种公式在不同的情况下都有其用途


关于性能,我认为对于任何由理智的程序员编写的常规java应用程序来说,差异都很小:)。

在您的例子中,第二个if只有在第一个if失败时才会被调用,所以这里不太重要,但是如果您的第一个if做了一些事情但没有返回,那么第二个if将被调用(这将永远是错误的)仍然会被测试,除非它是在一个else-if中

换句话说,在某些情况下,if-else-if和if-if之间的差异很重要,但这不是其中之一

示例:尝试此操作,然后在删除else后尝试。您将获得两种不同的输出:

int someNumber = 1;
if(someNumber < 5)
{
    someNumber += 5;
    Console.WriteLine("First call.");
}
else if(someNumber >= 5)
{
    Console.WriteLine("Second call.");
}
int someNumber=1;
如果(某些数字<5)
{
someNumber+=5;
控制台。WriteLine(“第一次呼叫”);
}
else if(someNumber>=5)
{
控制台。WriteLine(“第二次呼叫”);
}
  • 首先:

    P.>有人最终出于某种奇怪的原因,当你不看时,会添加一些附加语句,使这个方法在某些奇怪的条件下失败,每个人(或最坏的,一个人)将花费4小时。看源代码并调试应用程序,最终发现中间有什么东西。
  • 第二种肯定更好,它不仅可以防止这种情况,而且有助于清楚地表明,它不再是这样或那样

    如果我们在一个最多10行的
    If
    中编写的所有代码,这其实并不重要,但不幸的是,事实并非如此,还有其他程序员出于某种原因认为If体的长度应该大于200行……无论如何

  • 我不喜欢第三个,它迫使我寻找返回变量,而且更容易找到
    return
    关键字


关于速度性能,它们(几乎)是相同的。不要担心这一点。

在上一个示例中,不要这样做:

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}
但是这(注意Java的final的用法):

通过这样做,您可以清楚地表明您的意图,这是支持“按意图编程”的IDE的天赐之物(即使在部分AST上,也不需要“编译”来查看潜在错误,一个好的IDE可以实时检查不完整的源代码,并给您即时警告)

这样你就不会忘记初始化你的返回值。如果以后你决定你需要另一个条件,这是非常好的

自从我开始使用IntelliJ IDEA(很久以前的版本4左右)以来,我一直都在这样做,甚至更多,这让我避免了很多愚蠢的分心错误

有些人会争辩说,对于这样一个简单的例子来说,这是太多的代码了,但这完全没有抓住重点:重点是要明确意图,以便代码易于阅读,并且可以在以后轻松扩展,而不会意外忘记赋值返回,也不会意外忘记从后面的子句返回加上

否则,如果“简洁”是游戏的名称,那么我会写:

public boolean foo(int a) {
  return a > 10 ? doStuff() : a == 0 ? doOtherStuff() : false; 
}

doStuff和doOtherStuff都将返回true。

你几乎肯定是不正确的-任何现代编译器都会将它们优化为相同的代码
public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}
public boolean foo(int input) {
   final boolean toBeReturned;    // no init here
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   } else {
      toBeReturned = false;
   }
   return toBeReturned;
}
public boolean foo(int a) {
  return a > 10 ? doStuff() : a == 0 ? doOtherStuff() : false; 
}