什么是更好的方法来避免do-while(错误);破解Java?

时间:2013-08-30 09:28:52

标签: java do-while

当代码流如下:

if(check())
{
  ...
  ...
  if(check())
  {
    ...
    ...
    if(check())
    {
      ...
      ...
    }
  }
}

我一般都看到这种方法可以避免这种混乱的代码流:

do {
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
} while(false);

有哪些更好的方法可以避免这种变通/破解,从而使其成为更高级别(行业级别)的代码?

是否有可能来自Apache commons或Google Guava的构造?

注意:这是the same question for C++的副本。最好的答案是真正的函数指针和GOTO命令。两者都不存在于Java中。我对Java也是如此感兴趣。

将它放入一个新函数并使用 return 在我看来不是一个好的解决方案,因为return退出了该方法。因此,如果我的类有20个方法使用这些结构,我将不得不添加20个额外的方法来完成这个。这就是为什么GOTO是C ++的最佳答案。

4 个答案:

答案 0 :(得分:6)

要减少cyclomatic complexity,您可以将逻辑分成子方法:

public void go() {
    first();
}

public void first() {
    if(check()) {
        // #1
        second();
    }
}

public void second() {
    if(check()) {
        // #2
        third();
    }
}

public void third() {
    if(check()) {
        // #3
    }
}

答案 1 :(得分:6)

这是什么“而(假)”不存在?使用标签!

myLabel: {
    if(!check()) break myLabel;
    ...
    ...
    if(!check()) break myLabel;
    ...
    ...
    if(!check()) break myLabel;
    ...
}

它是核心Java:http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html

答案 2 :(得分:2)

  

因为你可以在函数中使用20次来传递20个连续步骤。如果我这样做,最后的if会向右滑动20个标签,这会使代码无法读取。

你的评论显示了这个问题:你想象的是错误的代码结构。

例如,您的代码就像这样

if (bool) {
     // do something
     if (anotherBoolean) {
         //do even more
         if (thirdBoolean) {
             // here we go! I spare deeper structure...
         }
     }
}

这可以很容易地重构为:

public void method() {
    if (bool) {
        doSomeStuff();
    }
}

public void doSomeStuff() {
    if (anotherBoolean) {
        doThirdStuff();
    }
}

public void doThirdStuff() {
    if (thirdBoolean) {
        doEvenMore();
    }
}

public void doEvenMore() {
    // deeper structure
}

这种代码结构将是Clean Code的一个很好的示例,因为这些方法正在执行它们的“单一用途”的东西,你不做一个while循环hack加上你甚至可能在某处重用这些方法。

答案 3 :(得分:1)

这是一个很好的问题。任何解决方案的语义必须涉及某种可激励的块,无论是字面还是可以退出的实现所暗示的。

其他一些答案非常复杂,以至于他们在避免使用do-while循环时会失去所有清晰度和可读性,这使得它们成为“糟糕”的代码。

经过一番思考,这就是我编码的方式:

doSomething(); // Replace current code with a method call

private void doSomething() {
    if(!check()) return;
    ...
    ...
    if(!check()) return;
    ...
    ...
    if(!check()) return;
    ...
    ...
}

要点:

  • 方法是一个块,由return
  • 干净地退出
  • 这三个部分显然可以作为一个编程单元,所以它们一起是重构为单独方法的字符串候选者
  • 没有“设计”,例如敷衍的do-while(false)结构,它只是为了提供一个可以使用的块而且可能会让其他人感到困惑
  • 通过使用否定测试然后退出,实现了两件事:
  • 不会创建额外的块/类/对象,从而保持可读性和性能(尽管框架将被推入堆栈以进行方法调用 - 影响可以忽略不计