替代Java中的goto语句

时间:2010-03-12 05:53:18

标签: java keyword goto

Java中 goto 关键字的替代功能是什么?

由于Java没有goto。

11 个答案:

答案 0 :(得分:81)

您可以使用带标签的BREAK声明:

search:
    for (i = 0; i < arrayOfInts.length; i++) {
        for (j = 0; j < arrayOfInts[i].length; j++) {
            if (arrayOfInts[i][j] == searchfor) {
                foundIt = true;
                break search;
            }
        }
    }

但是,在设计合理的代码中,您不需要GOTO功能。

答案 1 :(得分:41)

Java中没有与goto概念直接等价的东西。有一些结构允许您使用经典goto执行某些的操作。

  • breakcontinue语句允许您跳转循环或切换语句中的块。
  • 带标签的语句和break <label>允许您将任意复合语句跳出到给定方法(或初始化程序块)中的任何级别。
  • 如果标记循环语句,则可以continue <label>继续从内循环开始外循环的下一次迭代。
  • 抛出和捕获异常允许您(有效地)跳出方法调用的多个级别。 (但是,例外是相对昂贵的,被认为是做“普通”控制流 1 的坏方法。)
  • 当然,还有return

这些Java构造都不允许您在与当前语句相同的嵌套级别向后或向代码中的某个点进行分支。它们都跳出一个或多个嵌套(范围)级别,它们全部(除了continue)向下跳跃。此限制有助于避免旧BASIC,FORTRAN和COBOL代码 2 中固有的goto“spaghetti code”综合症。


1-异常中最昂贵的部分是异常对象及其堆栈跟踪的实际创建。如果您确实需要对“常规”流控制使用异常处理,则可以预先分配/重用异常对象,也可以创建覆盖fillInStackTrace()方法的自定义异常类。缺点是异常的printStackTrace()方法不会为您提供有用的信息......如果您需要调用它们。

2 - 意大利面条代码综合症产生了structured programming方法,在那里你限制了对可用语言结构的使用。这可以应用于BASICFortranCOBOL,但需要谨慎和纪律。完全摆脱goto是一个实用的更好的解决方案。如果你用一种语言保留它,总会有一些小丑会滥用它。

答案 2 :(得分:29)

为了好玩,here是Java中的GOTO实现。

  

实施例

   1 public class GotoDemo {
   2     public static void main(String[] args) {
   3         int i = 3;
   4         System.out.println(i);
   5         i = i - 1;
   6         if (i >= 0) {
   7             GotoFactory.getSharedInstance().getGoto().go(4);
   8         }
   9         
  10         try {
  11             System.out.print("Hell");
  12             if (Math.random() > 0) throw new Exception();            
  13             System.out.println("World!");
  14         } catch (Exception e) {
  15             System.out.print("o ");
  16             GotoFactory.getSharedInstance().getGoto().go(13);
  17         }
  18     }
  19 }
     

运行它:

$ java -cp bin:asm-3.1.jar GotoClassLoader GotoDemo           
   3
   2
   1
   0
   Hello World!

我是否需要添加“不要使用它!”?

答案 3 :(得分:17)

虽然一些评论者和下载者认为这不是 goto ,但是从下面的Java语句中生成的字节码确实表明这些语句确实表达了 goto 语义。 / p>

具体来说,第二个示例中的do {...} while(true);循环由Java编译器优化,以便不评估循环条件。

向前跳

label: {
  // do stuff
  if (check) break label;
  // do more stuff
}

字节码:

2  iload_1 [check]
3  ifeq 6          // Jumping forward
6  ..

向后跳

label: do {
  // do stuff
  if (check) continue label;
  // do more stuff
  break label;
} while(true);

字节码:

 2  iload_1 [check]
 3  ifeq 9
 6  goto 2          // Jumping backward
 9  ..

答案 4 :(得分:5)

如果你真的想要像goto语句这样的东西,你总是可以尝试打破命名块。

您必须在块的范围内才能打破标签:

namedBlock: {
  if (j==2) {
    // this will take you to the label above
    break namedBlock;
  }
}

我不会告诉你为什么你应该避免转到 - 我假设你已经知道了答案。

答案 5 :(得分:4)

public class TestLabel {

    enum Label{LABEL1, LABEL2, LABEL3, LABEL4}

    /**
     * @param args
     */
    public static void main(String[] args) {

        Label label = Label.LABEL1;

        while(true) {
            switch(label){
                case LABEL1:
                    print(label);

                case LABEL2:
                    print(label);
                    label = Label.LABEL4;
                    continue;

                case LABEL3:
                    print(label);
                    label = Label.LABEL1;
                    break;

                case LABEL4:
                    print(label);
                    label = Label.LABEL3;
                    continue;
            }
            break;
        }
    }

    public final static void print(Label label){
        System.out.println(label);
    }

答案 6 :(得分:3)

StephenC写道:

  

有两种结构可以让你做一些事情   可以用经典的转到。

再一次......

Matt Wolfe写道:

  

人们总是谈论从不使用goto,但我认为有一个   非常好的真实世界用例,这是众所周知和使用..   也就是说,确保在从a返回之前执行一些代码   功能..通常它的释放锁或什么不,但在我的情况下我   我希望能在回归之前能够休息一下,这样我才能做到   需要强制清理。

try {
    // do stuff
    return result;  // or break, etc.
}
finally {
    // clean up before actually returning, even though the order looks wrong.
}

http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html

  

当try块退出时,finally块始终执行。这个   确保即使意外发生也执行finally块   异常发生。但最终对于不仅仅是异常更有用   处理 - 它允许程序员避免使用清理代码   被意外绕过返回,继续或休息。进行清理   finally块中的代码总是很好的做法,即使没有   预计有例外。

与finally相关的愚蠢的面试问题是:如果你从try {}块返回,但是在你的finally {}中也返回了,返回了哪个值?

答案 7 :(得分:1)

最简单的是:

int label = 0;
loop:while(true) {
    switch(state) {
        case 0:
            // Some code
            state = 5;
            break;

        case 2:
            // Some code
            state = 4;
            break;
        ...
        default:
            break loop;
    }
}

答案 8 :(得分:0)

尝试以下代码。它对我有用。

for (int iTaksa = 1; iTaksa <=8; iTaksa++) { // 'Count 8 Loop is  8 Taksa

    strTaksaStringStar[iCountTaksa] = strTaksaStringCount[iTaksa];

    LabelEndTaksa_Exit : {
        if (iCountTaksa == 1) { //If count is 6 then next it's 2
            iCountTaksa = 2;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 2) { //If count is 2 then next it's 3
            iCountTaksa = 3;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 3) { //If count is 3 then next it's 4
            iCountTaksa = 4;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 4) { //If count is 4 then next it's 7
            iCountTaksa = 7;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 7) { //If count is 7 then next it's 5
            iCountTaksa = 5;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 5) { //If count is 5 then next it's 8
            iCountTaksa = 8;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 8) { //If count is 8 then next it's 6
            iCountTaksa = 6;
            break  LabelEndTaksa_Exit;
        }

        if (iCountTaksa == 6) { //If count is 6 then loop 1  as 1 2 3 4 7 5 8 6  --> 1
            iCountTaksa = 1;
            break  LabelEndTaksa_Exit;
        }
    }   //LabelEndTaksa_Exit : {

} // "for (int iTaksa = 1; iTaksa <=8; iTaksa++) {"

答案 9 :(得分:-1)

使用标记的中断作为转到的替代方法。

答案 10 :(得分:-1)

Java没有goto,因为它会使代码非结构化不清楚来阅读。但是,您可以使用breakcontinue作为 goto 文明形式,而不会出现问题。


使用break -

向前跳跃
ahead: {
    System.out.println("Before break");
    break ahead;
    System.out.println("After Break"); // This won't execute
}
// After a line break ahead, the code flow starts from here, after the ahead block
System.out.println("After ahead");

<强>输出

Before Break
After ahead

使用继续

向后跳跃
before: {
    System.out.println("Continue");
    continue before;
}

每次执行continue before行时都会产生无限循环代码流将从before 重新开始。