プログラムdeタマゴ

nodamushiの著作物は、文章、画像、プログラムにかかわらず全てUnlicenseです

JavaでGOTOライク

 指定したところへ一気に飛べるgoto文はプログラミングにおいて禁じ手とされている。可読性が下がるからだ。
 そのため、Javaにははじめからgoto文というものは存在しない
 しかし、こんな場合はどうだろう。読みにくい。

if(〜){
    boolean b=true;//以降の処理を抜ける為のフラグ
    if(〜){
        ………
    }else{
        
        for(〜){
            if(〜){
                ………
                b=false;
                break;//ここで一番外のif文の外に出たい
            }
        }
            
        if(b){
            if(〜){
                ………
            }else{
                ………
            }
        }
    }
    if(b){
        ………
    }
}


 ただでさえネストが深いコードなのにさらにbのおかげで読みにくい。
 こんなにネストする方が悪い?
 仕方ないじゃない、実際に書いてたら出てきたソースなんだから。(ただ、おおよその場合は、ローカル変数を格納するクラスを作って、関数化すべき。returnで処理を抜けよう)

 こういうときはbreak文で一気にif文の外に出てしまった方が可読性的にも実行速度的にも良い。

 Javaにおけるbreak文はループから抜ける単なる「break;」と、ラベルを付けたブロックから抜ける「break ラベル名;」の二つがある。
 この「break ラベル名;」は入門書とかで

LABEL1:for(〜){
    for(〜){
        ………
        break LABEL1;
    }
}

 こんな風に紹介されているからてっきりループにしか指定できないと思っている人は多いと思う。私も最初はそう思っていた。
 が、さっきも書いたようにラベルを付けたブロックから抜けるのが「break ラベル名」だ。つまりブロックだったら何でも良い。だから、下は正しい。

LABEL1:{
    ………
    break LABEL1;
    ………
}

 ただし、推奨された使い方ではないのでむやみやたらと使うべきではない。やはり可読性が下がるからね。

 これを利用すると、if分もブロックの一つだからさっきの長ったらしいのは以下のように簡略化できる。

LABEL1:if(〜){ //if(〜)LABEL1:{ でもいい。個人的にはこっちが好き。
    if(〜){
        ………
    }else{    
        for(〜){
            if(〜){
                ………
                break LABEL1;//ここで一番外のif文の外に出る
            }
        }
            
        if(〜){
            ………
        }else{
            ………
        }
    }   
    ………
}

 bが消えた分、無駄な労力が省けたね。


 なお、「if()Label:」の書き方は問題ないけど、「for()Label:」と書くのはやめておきましょう。(breakしても、ブロックを抜けるだけでfor文自体は抜けない)