namalfernandolk
namalfernandolk

Reputation: 9134

Labled break inside java methods

Why java allows to use the labled break inside a method? Is there any special purpose or use of this? I thought it can be only use within the loops and swtches.

public void testMeth(int count){
   label:
   break label;
}

But below gives a compiler error.

public void testMeth(int count){
    break; // This gives an Error : break cannot be used outside of a loop or a switch
}

Upvotes: 4

Views: 1975

Answers (7)

Sauer
Sauer

Reputation: 1469

I strongly discurage the use of a labled break statement. It is almost as bad as a GOTO. A single break; is ok/necessary to end a loop or switch etc. But to my experience: The need for such a labled break is an indicator for a bad control-flow-design.

In most cases, a well placed exception would be more meaningful. But just, if the "Jump-Condition" can be seen as an Error. If you lable your method correctly, you can influence, what can be seen as an Error or not.

If your method is called "getDrink()" and it returns a "milk" object, it is ok. But if your method is called "getWater()", it should throw an Exception instead of returning milk...

So instead of:

public class TestBad {

public static void main(String[] args) {
    String[] guys = {"hans", "john"};

    myLabel: {
        for(String guy: guys) {
            String drink = getDrink(guy);

            if(drink.equals("milk")) {
                // Handle "milk"??
                break myLabel;
            }

            // Do something with "non-milk"
        }
    }

    // Success? Non Success??
}

private static String getDrink(String guy) {
    if(guy.equals("hans"))
        return "milk";
    else
        return "water";
}

}

You should use:

public class TestGood {

public static void main(String[] args) {
    String[] guys = {"hans", "john"};

    try {
        handleStuff(guys);
    } catch (Exception e) {
        // Handle Milk here!
    }
}

private static void handleStuff(String[] guys) throws Exception {
    for(String guy: guys) {

        String drink = getWater(guy);

        // Do something with "water"
    }
}

private static String getWater(String guy) throws Exception {
    if(guy.equals("hans"))
        // The method may NEVER return anything else than water, because of its name! So:
        throw new Exception("No Water there!");
    else
        return "water";
}

}

Fazit: Instead of nesting Blocks into Blocks or multiple loops, one should nest methods and use proper exception handling. This enhances readability and reusability.

Upvotes: 0

Nathan Ryan
Nathan Ryan

Reputation: 13041

Here is yet another example of when labels are useful outside the context of a loop:

boolean cond1 = ...
if (cond1) {
    boolean cond1 = ...
    if (cond2) {
        boolean cond3 = ...
        if (cond3) {
            bar();
        } else {
            baz();
        }
    } else {
        baz();
    }
} else {
    baz();
}

...becomes...

label: {
    boolean cond1 = ...
    if (cond1) {
        boolean cond1 = ...
        if (cond2) {
            boolean cond3 = ...
            if (cond3) {
                bar();
                break label;
            }
        }
    }
    baz();
}

A contrived example, obviously, but slightly more readable. My recommendation is that if you feel the need to use a label, pretty much ever, you should otherwise refactor the code.

Upvotes: 0

assylias
assylias

Reputation: 328608

I don't know the why, but the behaviour is specified in the Java Language Specification #14.15:

Break with no label

A break statement with no label attempts to transfer control to the innermost enclosing switch, while, do, or for statement of the immediately enclosing method or initializer; this statement, which is called the break target, then immediately completes normally.
If no switch, while, do, or for statement in the immediately enclosing method, constructor, or initializer contains the break statement, a compile-time error occurs.

Break with label (emphasis mine)

A break statement with label Identifier attempts to transfer control to the enclosing labeled statement (§14.7) that has the same Identifier as its label; this statement, which is called the break target, then immediately completes normally. In this case, the break target need not be a switch, while, do, or for statement.

Breaks with label enable you to redirect the code after a whole block (which can be a loop), which can be useful in the case of nested loops. It is however different from the C goto statement:

Unlike C and C++, the Java programming language has no goto statement; identifier statement labels are used with break (§14.15) or continue (§14.16) statements appearing anywhere within the labeled statement.

Upvotes: 2

namalfernandolk
namalfernandolk

Reputation: 9134

I found one crazy use by my self.

public void testMeth(int count){
    label: if (true) {
          System.out.println("Before break");
          if (count == 2) break label;
          System.out.println("After break");
    }
    System.out.println("After IF");
}

OR

public void testMeth(int count){

    namedBlock: {
        System.out.println("Before break");
        if (count == 0) break namedBlock;
        System.out.println("After break");
    }

    System.out.println("After Block");
}

This ignores the "After break".

Upvotes: 0

ChristopheD
ChristopheD

Reputation: 116157

You can use this to break out of nested loops immediately:

out: { 
         for( int row=0; row< max; row++ ) {
             for( int col=0; col< max; col++ )
                 if( row == limit) break out;
             j += 1;
         }
     }

Using break outside of loops does not make a whole lot of sense, where would you be breaking of? To break out of a void function you can use return as adarshr points out.

Upvotes: 2

adarshr
adarshr

Reputation: 62593

Because there is the return statement for use outside the loops!

public void testMeth(int count){
    if(count < 0) {
        return;
    }

    // do something with count
}

Upvotes: 0

michael667
michael667

Reputation: 3260

You can use labeled breaks to get out of nested loops, like here.

Upvotes: 0

Related Questions