86

What is an alternative function for the goto keyword in Java?

Since Java does not have a goto.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
gmhk
  • 15,598
  • 27
  • 89
  • 112
  • 2
    @cherouvim - its OK ... he can't, even if he wants to :-) – Stephen C Mar 12 '10 at 06:14
  • 10
    @harigm: Can you give an example of the kind of code that you would write _if_ `goto` is available in Java? I think therein lies the more important issue. – polygenelubricants Mar 12 '10 at 06:18
  • 3
    @harigm: I second polygene, could you please update your question to include why your program needs a goto? – Everyone Mar 12 '10 at 07:16
  • @cherouvim-I am in while loop, during iteration, there are 3 conditions, based on each condition criteria, I want to transfer the controlto that directly – gmhk Mar 13 '10 at 02:59
  • Actually, Java has the keyword _goto_ however there is no situation in which you can use it. e.g. const. Instead of goto, you can use continue, break, switch, return from a sub-method. It depends on what you are trying to do. – Peter Lawrey Nov 02 '10 at 22:37
  • 13
    People always talk about never using a goto, but I think there is a really good real world use case which is pretty well known and used.. That is, making sure to execute some code before a return from a function.. Usually its releasing locks or what not, but in my case I'd love to be able to jump to a break right before the return so I can do required mandatory cleanup. Of course a program littered with goto's all over the place would be horrible, but if restricted to method bodies it doesn't seem that bad as long as you follow a convention (only jump to the end of functions, never back up) – Matt Wolfe Sep 22 '11 at 08:45
  • 7
    You're in good company. Linus Torvalds has passionately defended goto http://kerneltrap.org/node/553. Undoubtedly the most notable omission from Project Coin. – Fletch Dec 01 '11 at 12:04
  • I am facing same problem too. Hence I am using continue, but it is showing error that- not a loop lable: myLable. Does continue work only with loops? – Sachin Mhetre Apr 17 '12 at 10:55
  • 7
    @MattWolfe doesn't try-finally do the job in that example? – Andres Riofrio Sep 24 '12 at 20:56
  • try/finally works well in most cases and I would argue that it is sufficient. The only drawback is that you can't just jump to the finally clause (easily). Perhaps you can manually throw an exception that you are catching silently to do so though (not sure if that works but I don't see why it wouldn't). – Matt Wolfe Sep 24 '12 at 21:34
  • 1
    @MattWolfe instead, you can use an if statement to block out the rest of your code. :) – Andres Riofrio Sep 24 '12 at 21:38
  • You need to imagine code that is deeply nested already though.. How do you prevent someone from writing some code in the future that gets run outside that if statement.. say you're already 3 levels deep in if statements when you get to this point where you determine you need to clean up and exit the routine. – Matt Wolfe Sep 24 '12 at 21:44
  • @MattWolfe `finally` captures the path of execution for `break` too, so you can jump to the finally with `try { do { break; } while (false) } finally { }` but of course `finally` is only necessary there if you're `return`ing or expecting an exception as well as doing the `break`: if you're only `break`ing then `do{ } while(false)` will suffice. – android.weasel Feb 07 '13 at 14:48
  • I didn't realize you could break from a try statement. Nice! – Matt Wolfe Feb 07 '13 at 16:20
  • @Matt. You can't "break from a try statement". The break is from the "do". The point is, when the end of the try is reached -- by whatever means -- the finally will execute. Even if you use a "return". The definition of finally is that it ***will*** execute when control leaves the "try". No matter how. So if you have code you want to skip, and don't see any easy way to wrap that in an "if" as Andres suggests, put the try/finally into its own routine, so that you can use "return". – ToolmakerSteve Nov 21 '13 at 01:46
  • Good point, try{}finally{} is probably a better solution in most cases to goto statements. FWIW I've never used a goto statement in c or any other language that supports it. – Matt Wolfe Nov 21 '13 at 01:58
  • @gmhk: 3 conditions: Switch if the 3 differ only in value (case 1, case 2, case 3). "If / else if / else", for more complex conditions. – ToolmakerSteve Nov 21 '13 at 04:21
  • You can use gotos properly (if there is such a term) using this bytecode modification library https://github.com/footloosejava/JavaGoto – The Coordinator May 16 '14 at 21:38
  • @gmhk you are making a wrong assumption. Java since I rememeber has always had the `goto` keyword. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html . ( Trust me it's a very tricky certification question. ) – Ruslan López Oct 27 '15 at 17:50

12 Answers12

86

You could use a labeled BREAK statement:

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;
            }
        }
    }

However, in properly designed code, you shouldn't need GOTO functionality.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Padmarag
  • 7,067
  • 1
  • 25
  • 29
  • 90
    This will not save you from the raptors! – Bobby Nov 02 '10 at 18:50
  • 26
    Why should you not need goto functionality in properly designed code? – rogermushroom Nov 16 '11 at 17:42
  • 14
    Because assembly is the only one allowed to use it. A while statement, a for statement, a do-while, a foreach, a function call, all of these are GOTO statements used in a controlled and predictable manner. On the level of the assembler, it will always be GOTOs, but you should not need the functionality that pure GOTO gives you - its only advantage over functions and loop/control statements is that it lets you jump in the middle of any code, anywhere. And that 'advantage' is itself the definition of 'spaghetti code'. –  Mar 16 '12 at 22:34
  • 2
    @whatsthebeef Here's the famous 1968 letter by Edsger W. Dijkstra that explains why he [considered goto harmful](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.92.4846&rep=rep1&type=pdf). – thomanski Apr 02 '12 at 12:58
  • 1
    @zode64 I am pretty convinced that a well written code for example at the case of using double loops will throw this out to a method, and use return instead of breaking blocks. I was working with a guy, he learned to program in the 80's and he wrote 1000-1500 lines of methods in java, using blocks, breaks, and altogether instead of trying to repair his code we simply replaced it based on User Requirement Specification. I believe "goto-like" programming belongs to the pre 90's and should stay there. Really. – CsBalazsHungary Feb 07 '13 at 14:52
  • A while loop is a goto statement. Also, I can think of a few situations where a goto would be more elegant, but in all of those situations you could use a while statement instead. Maybe it's all of the assembly I wrote, but in those cases, the goto statement always seems to be the 'correct' answer, even if it is the unsafe answer. The while loop always seems post-facto. –  May 29 '13 at 11:22
  • @RiverC. Please don't say "a while loop is a goto statement." Yes, the compiler IMPLEMENTS it using a branch. BUT THAT IS NOT THE POINT. When encountering a goto, you have to ask yourself: WHY is this branching? Does it branch in a safe manner? Could this be the cause of some bug? When encountering a routine with multiple gotos, my reaction based on debugging experience is "this is going to be bad". Modern control flow constructs (while, etc) tell you exactly what is going on. Easy to understand, hard to abuse. Sometimes, clean solution is to factor out a method, replace gotos with returns. – ToolmakerSteve Nov 21 '13 at 04:13
  • @ToolmakerSteve There is currently no other way to implement such an iteration. It is better to understand a while statement as a subset of GOTO statements, which allows you to understand what is going on under the hood. –  Nov 27 '13 at 21:43
  • @RiverC: ahh, rereading ALL your comments, I now read differently the point of your statement "A while loop is a goto statement". I first read it as cavalier, like it didn't really matter whether one used "while" or "goto", since the end result is the same. (doesn't matter to the computer, but matters to human understanding, and writing robust code -- this is what bothered me) Now I read it as a response to zode64's "Why not need goto ...". You are explaining that the "goto" statement isn't needed, because these other statements, each of which is a subset of "goto", together cover the needs. – ToolmakerSteve Nov 27 '13 at 21:59
  • 12
    [Context for "raptors"](http://www.explainxkcd.com/wiki/index.php/292:_goto), xkcd [#292](http://www.xkcd.com/292/). – Peter Mortensen Jan 31 '14 at 16:28
  • Mojang **actually** uses this godforsaken thing in Minecraft's source... =/ – arkon Aug 28 '14 at 22:04
  • 1
    I still haven't seen a good example of how to "properly design" code in a situation where you have series of tasks and if any one of them fails you e.g. give out the same error message. Sure, you could put the code to show the error into a function and call it and then return, but that's not "properly designed" in my book. Sure, you could have a booelan `didThisErrorHappen` and if yes, show error and return, but that doesn't seem "properly designed" to me either, really. I'd rather just use goto. But purists don't seem to like it, even though properly used it is just another way to structure. – Sami Kuhmonen Dec 28 '14 at 18:42
43

There isn't any direct equivalent to the goto concept in Java. There are a few constructs that allow you to do some of the things you can do with a classic goto.

  • The break and continue statements allow you to jump out of a block in a loop or switch statement.
  • A labeled statement and break <label> allow you to jump out of an arbitrary compound statement to any level within a given method (or initializer block).
  • If you label a loop statement, you can continue <label> to continue with the next iteration of an outer loop from an inner loop.
  • Throwing and catching exceptions allows you to (effectively) jump out of many levels of a method call. (However, exceptions are relatively expensive and are considered to be a bad way to do "ordinary" control flow1.)
  • And of course, there is return.

None of these Java constructs allow you to branch backwards or to a point in the code at the same level of nesting as the current statement. They all jump out one or more nesting (scope) levels and they all (apart from continue) jump downwards. This restriction helps to avoid the goto "spaghetti code" syndrome inherent in old BASIC, FORTRAN and COBOL code2.


1- The most expensive part of exceptions is the actual creation of the exception object and its stacktrace. If you really, really need to use exception handling for "normal" flow control, you can either preallocate / reuse the exception object, or create a custom exception class that overrides the fillInStackTrace() method. The downside is that the exception's printStackTrace() methods won't give you useful information ... should you ever need to call them.

2 - The spaghetti code syndrome spawned the structured programming approach, where you limited in your use of the available language constructs. This could be applied to BASIC, Fortran and COBOL, but it required care and discipline. Getting rid of goto entirely was a pragmatically better solution. If you keep it in a language, there is always some clown who will abuse it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Looping constructs like **while(...){}** and **for(...){}** allow you to repeat blocks of code without explicitly jumping to an arbitrary location. Also, method calls **myMethod()** allow you to execute code found elsewhere and return to the current block when finished. All of these can be used to replace functionality of **goto** while preventing the common problem of failing to return that goto allows. – Chris Nava Mar 12 '10 at 15:00
  • @Chris - that is true, but most languages that support GOTO also have closer analogs to Java loop constructs. – Stephen C Mar 13 '10 at 01:41
  • 1
    @Chris - classic FORTRAN has 'for' loops and classic COBOL also has looping constructs (though I can't recall the details). Only classic BASIC has no explicit looping constructs ... – Stephen C Nov 23 '11 at 00:29
31

Just for fun, here is a GOTO implementation in Java.

Example:

   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 }

Running it:

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

Do I need to add "don't use it!"?

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
18

While some commenters and downvoters argue that this isn't goto, the generated bytecode from the below Java statements really suggests that these statements really do express goto semantics.

Specifically, the do {...} while(true); loop in the second example is optimised by Java compilers in order not to evaluate the loop condition.

Jumping forward

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

In bytecode:

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

Jumping backward

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

In bytecode:

 2  iload_1 [check]
 3  ifeq 9
 6  goto 2          // Jumping backward
 9  ..
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
  • How does the do/while jump backwards? It still just breaks out of the block. Counter Example: label: do {System.out.println("Backward"); continue label;} while(false); I think in your example the while(true) is what is responsible for the backwards jump. – Ben Holland Dec 31 '12 at 22:33
  • @BenHolland: `continue label` is the jump backwards – Lukas Eder Jan 01 '13 at 11:11
  • I'm still not convinced. The continue statement skips the current iteration of a for, while, or do-while loop. The continue skips to the end of the loop's body, which is then evaluated for the boolean expression that controls the loop. The while is what is jumping backwards not the continue. See http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html – Ben Holland Jan 05 '13 at 19:55
  • @BenHolland: Technically you're right. From a logical perspective, if `// do stuff` and `// do more stuff` are the statements of interest, `continue label` *"has the effect"* of jumping backwards (due to the `while(true)` statement of course). I wasn't aware that this was such a precise question, though... – Lukas Eder Jan 05 '13 at 22:52
  • 2
    @BenHolland: I updated the answer. The `while(true)` is translated by the compiler into a `goto` bytecode operation. As `true` is a constant literal, the compiler can do this optimisation and doesn't have to evaluate anything. So, my example really is a goto, jumping backwards... – Lukas Eder Jan 06 '13 at 19:40
  • Examining the byte codes (or native instructions) to determine whether you branch forward or backwards is missing the point. It is well known that "goto" primitives exists at that level. The direction of a jump instruction is determined by the compiler has chosen to arrange the code blocks, not by programming language level semantics. – Stephen C Nov 16 '14 at 01:44
  • Likewise, the fact that in some cases you can write code that is directly equivalent to code that you can write using `goto` statements is also missing the point. The issue with `goto` and why it is "considered harmful" is the way that the semantics are *expressed* ... and the impact that has on *source code level* readability. (Especially when `goto` is abused.) – Stephen C Nov 16 '14 at 01:49
  • This is indeed the closest equivalent. The only difference is that it creates a new scope for the `do` `while`, but then we could put declarations just outside it. – Ciro Santilli OurBigBook.com Mar 30 '15 at 07:08
  • Wow I just learned something. break without a loop. Who'd have known! This can actually be useful. – Stefan Reich Dec 04 '17 at 12:43
  • @StefanReich: Yeah, it's a controversial topic - not everyone will like you for using this feature, but I find it useful (very rarely) as well. [Here's a blog post I've written about that, recently](https://blog.jooq.org/2017/07/14/dont-extract-everything-into-a-method/) – Lukas Eder Dec 07 '17 at 08:15
5

If you really want something like goto statements, you could always try breaking to named blocks.

You have to be within the scope of the block to break to the label:

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

I won't lecture you on why you should avoid goto's - I'm assuming you already know the answer to that.

bluish
  • 26,356
  • 27
  • 122
  • 180
Amir Afghani
  • 37,814
  • 16
  • 84
  • 124
  • 2
    I tried implementing this in my SO question [linked here](http://stackoverflow.com/questions/22263245/labeled-break-ignored-or-treated-as-normal-break). It actually doesn't take you to the "label above," perhaps I misinterpreted the author's statements, but for clarity I'll add that it takes you to the end of the outer block (the "labeled" block), which is below where you are breaking. Hence you cannot "break" upwards. At least that is my understanding. – NameSpace Mar 20 '14 at 00:33
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);
    }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
code lover
  • 41
  • 1
  • This will result in a StackOverFlowException is you run it long enough, thus my need to goto. – Kevin Parker Jun 10 '12 at 16:04
  • 3
    @Kevin: How will this lead to a stack overflow? There's no recursion in this algorithm... – Lukas Eder Nov 21 '12 at 13:32
  • 1
    This looks very much like the original proof that any program can be written without using "goto" - by turning it into a while loop with a "label" variable which is ten times worse than any goto. – gnasher729 Jun 12 '14 at 22:21
3

StephenC writes:

There are two constructs that allow you to do some of the things you can do with a classic goto.

One more...

Matt Wolfe writes:

People always talk about never using a goto, but I think there is a really good real world use case which is pretty well known and used.. That is, making sure to execute some code before a return from a function.. Usually its releasing locks or what not, but in my case I'd love to be able to jump to a break right before the return so I can do required mandatory cleanup.

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

The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

The silly interview question associated with finally is: If you return from a try{} block, but have a return in your finally{} too, which value is returned?

android.weasel
  • 3,343
  • 1
  • 30
  • 41
  • 2
    I disagree that that is a silly interview question. An experienced Java programmer *should* know what happens, if only to understand *why* putting a `return` in a `finally` block is a bad idea. (And even if the knowledge is not strictly necessary, I'd be worried by a programmer who didn't have the curiosity to find out ...) – Stephen C Nov 16 '14 at 01:35
1

The easiest is:

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;
    }
}
ratchet freak
  • 47,288
  • 5
  • 68
  • 106
0

Try the code below. It works for me.

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++) {"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mahasam
  • 829
  • 7
  • 8
0

In modern Java I would just use switch and String. I am surprised that I couldn't find this answer:

for (String label = "start";;) {
    switch (label) {
        case "start":
           ...
        case "something":
           ...
        case "whatever":
           ...
           label = "something"; break; // <== those two commands equal goto
           ...
        default:
           return;
    }

}
maraca
  • 8,468
  • 3
  • 23
  • 45
-1

Use a labeled break as an alternative to goto.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
apoorva
  • 195
  • 1
  • 2
  • 13
-1

Java doesn't have goto, because it makes the code unstructured and unclear to read. However, you can use break and continue as civilized form of goto without its problems.


Jumping forward using 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");

Output:

Before Break
After ahead

Jumping backward using continue

before: {
    System.out.println("Continue");
    continue before;
}

This will result in an infinite loop as every time the line continue before is executed, the code flow will start again from before.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Confuse
  • 5,646
  • 7
  • 36
  • 58
  • 2
    Your example on jumping backward using continue is wrong. You cannot use "continue" outside the body of a loop, it cause a compile error. Inside a loop, however, continue simply jumps the loop conditional. So something like while(true){continue;} would be an infinite loop, but so is while(true){} for that matter. – Ben Holland Feb 20 '15 at 00:06