替代Java中的goto语句

gmh*_*mhk 83 java goto keyword

Java中goto关键字的替代函数是什么?

由于Java没有goto.

Pad*_*rag 82

您可以使用带标签的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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

  • 这不会让你免于猛禽! (87认同)
  • 为什么在正确设计的代码中不需要goto功能? (25认同)
  • 因为汇编是唯一允许使用它的人.while语句,for语句,do-while,foreach,函数调用,所有这些都是以受控和可预测的方式使用的GOTO语句.在汇编程序的层面上,它总是GOTO,但你不应该需要纯GOTO给你的功能 - 它比函数和循环/控制语句的唯一优势是它可以让你在任何地方的任何代码中间跳转.而"优势"本身就是"意大利面条代码"的定义. (12认同)
  • ["猛禽"的背景](http://www.explainxkcd.com/wiki/index.php/292:_goto),xkcd [#292](http://www.xkcd.com/292/). (9认同)
  • @whatsthebeef 这是 Edsger W. Dijkstra 于 1968 年写的著名信件,解释了为什么他[认为 goto 有害](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.92.4846&amp;rep=rep1&amp;type=pdf) 。 (2认同)

Ste*_*n C 42

goto在Java中没有任何直接等同的概念.有一些结构可以让你做一些经典的事情goto.

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

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


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

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


Pas*_*ent 30

只是为了好玩,是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 }
Run Code Online (Sandbox Code Playgroud)

运行它:

$ java -cp bin:asm-3.1.jar GotoClassLoader GotoDemo           
   3
   2
   1
   0
   Hello World!
Run Code Online (Sandbox Code Playgroud)

我需要添加"不要使用它!"?

  • 错误:`Math.random()` 可以返回 0。它应该是 &gt;= (2认同)

Luk*_*der 17

虽然一些评论者和下载者认为这不是goto,但是来自以下Java语句的生成字节码确实表明这些语句确实表达了goto语义.

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

向前跳

label: {
  // do stuff
  if (check) break label;
  // do more stuff
}
Run Code Online (Sandbox Code Playgroud)

在字节码中:

2  iload_1 [check]
3  ifeq 6          // Jumping forward
6  ..
Run Code Online (Sandbox Code Playgroud)

向后跳

label: do {
  // do stuff
  if (check) continue label;
  // do more stuff
  break label;
} while(true);
Run Code Online (Sandbox Code Playgroud)

在字节码中:

 2  iload_1 [check]
 3  ifeq 9
 6  goto 2          // Jumping backward
 9  ..
Run Code Online (Sandbox Code Playgroud)

  • @BenHolland:我更新了答案.编辑器将`while(true)`转换为`goto`字节码操作.由于`true`是一个常量字面值,编译器可以执行此优化,而不必评估任何内容.所以,我的例子真的是一个转向,向后跳...... (2认同)

Ami*_*ani 5

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

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

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

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

  • 我尝试在我的问题[在这里链接](http://stackoverflow.com/questions/22263245/labeled-break-ignored-or-treated-as-normal-break)中实现这一点.它实际上并没有带你到"上面的标签",也许我误解了作者的陈述,但为了清楚起见,我将补充说它会带你到外部块的末尾("标记"块),这是在下面你在哪里打破.因此,你不能向上"打破".至少这是我的理解. (2认同)