Javaはgotoを使える?詳しく解説!Javaではgotoは使えないが、代わりの手段は沢山ある

- システム
エンジニア - Javaのgotoとはどのようなものなのでしょうか。
- プロジェクト
マネージャー - Javaのgotoについて概要などを説明しますので、一緒に見ていきましょう。
Javaのgotoとは?
gotoという命令文が使えるプログラム言語は多くあります。BASICやC言語、C#といった言語はgoto文を使用できます。Javaでのgotoについて解説する前に、gotoがどんな命令文なのかを解説しましょう。
1 2 3 4 |
10 input a 20 print a 30 goto 10 |
このプログラムはBASICで記述されていて、inputで入力された内容をprintで表示して、それを永久に繰り返します。繰り返しはgotoで行番号10の行に戻ることで実現しています。gotoとはプログラムの指定された箇所に移る命令なのです。
行番号がない言語はラベルにジャンプする
ただしプログラム言語の多くはBASICと違って行番号がありません。そういった言語のgotoはラベルにジャンプします。以下はC言語でgotoを利用した例です。
1 2 3 4 5 6 7 |
int main(void){ int cnt = 1; LOOP: printf("%d回目です\n",cnt); if (cnt++ < 3) goto LOOP; } |
実行すると以下のように表示されます。cntが3になるまでラベルのLOOPの箇所にgotoで戻って繰り返しています。
1回目です
2回目です
3回目です
Javaでgotoを使用してみる
では上のC言語のサンプルと同じ処理をJavaで記述してみましょう。以下のようになります。
1 2 3 4 5 6 7 8 9 10 |
public class MainClass { public static void main(String[] args) { int cnt = 1; LOOP: System.out.println(cnt + "回目です。"); if (cnt++ < 3) goto LOOP; } } |
しかし、結果はgoto LOOPの箇所がエラーになります。なぜでしょうか。
Javaでgotoは使えない
結論から言うと、Javaでgotoは使えません。gotoについてネットで調べると、gotoを使うことに否定的な意見が多く見られます。BASICと違いC言語やJavaは構造化プログラミング言語であり、gotoのように処理を直接制御するような命令文は使うべきでないとされているからです。
ちなみにBASICのような行番号がある言語は手続き型プログラミング言語と言います。しかし現在多く使われているVisual Basicでは行番号もgotoも使用しないのが普通なので、gotoを使うプログラミングは推奨されてないと言えるでしょう。
Javaではgotoは予約語になっている
ただ、上のJavaサンプルを入力して不思議な事に気付いた人もいるでしょう。Eclipseなどの環境で入力した場合、gotoはエラーになるものの、intやifなどと同じように色付けされています。
それはgotoがJavaの予約語だからです。そのため以下のようにgotoを変数名に使用するとエラーになります。
1 2 3 |
int goto = 1; System.out.println(goto); |
これは矛盾しているように感じますが、Javaでgotoを使えなくしたものの、C#などのライバルの言語では使えるため、Javaでも将来使えるようにできる可能性を残したのだと思われます。
breakでgotoに近いことが出来る
ではJavaではgotoのようなことはできないのでしょうか?実はgotoに変わる方法があります。以下のサンプルをご覧ください。
1 2 3 4 5 6 7 8 9 10 11 12 |
public class MainClass { public static void main(String[] args) { int cnt = 1; LOOP: while (true) { System.out.println(cnt + "回目です。"); if (cnt++ >= 3) break LOOP; } } } |
break+ラベル名でgotoに近いことが出来る
Javaは上のサンプルのようにwhileループやforループの前に「ラベル名+:」を記述することができます。そして「break+ラベル名」でループから抜け出すことが出来るのです。結果は以下のようになります。while(true)の無限ループから3回目で抜け出すことで、C言語のサンプルと近い事が実現できています。
1回目です。
2回目です。
3回目です。
ラベル付きbreakの有効な使い方
ただし上のJavaサンプルでは、ラベルがなかったとしても普通のbreakで同じように動作します。ラベル付きbreakの有効な使い方は以下のような多重ループのケースです。
1 2 3 4 5 6 7 |
LABEL: for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { System.out.println(i + " " + j); if (j==1) break LABEL; // 一番外に抜けられる } } |
ラベル付きbreakでスマートに
上のJavaサンプルの実行結果は、
0 0
0 1
となります。iが0の時にjが1だったらそこでループを打ち切っています。これをもしラベルを使わないで行う場合、以下のようにフラグを使う必要があります。ラベルを使えばスマートになりますね。
1 2 3 4 5 6 7 8 9 10 11 12 |
for (int i = 0; i < 3; i++) { boolean break_flag = false; for (int j = 0; j < 3; j++) { System.out.println(i + " " + j); if (j==1) { break_flag = true; break; } } if (break_flag) break; } |
ラベル付きcontinueも便利
Javaはループをスキップする命令文のcontinueにもラベルを付けることが出来ます。以下がその例です。
1 2 3 4 5 6 7 |
LABEL: for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { System.out.println(i + " " + j); if (j==1) continue LABEL; } } |
ラベル付きcontinueも有効活用しよう
上のJavaサンプルを実行すると以下の結果になります。jが2の時の処理がcontinueでスキップされています。
0 0
0 1
1 0
1 1
2 0
2 1
もしラベル付きcontinueを使わずに同じことをする場合、以下のようになります。こちらはラベル付きbreakを使わない時よりさらに複雑になりますね。
1 2 3 4 5 6 7 8 9 10 11 12 |
boolean continue_flag = false; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (continue_flag) { continue_flag = false; continue; } System.out.println(i + " " + j); if (j==1) continue_flag = true; } } |
例外処理もgotoに近いことが出来る
他にgotoに近いことが出来るJavaの機能は、例外処理です。以下のようにすれば可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class MyException extends Exception { private static final long serialVersionUID = 1L; } public class MainClass { public static void main(String[] args) { try { // 色々な処理 throw new MyException(); // 色々な処理 } catch (MyException e) { // 例外処理A } catch (Exception e) { // 例外処理B } } } |
上のJavaサンプルのように、Exceptionクラスを継承して独自のExceptionクラスを作って、必要な場合にそれをthrowして、try~catchでその独自の例外を受ければ、意図通りに制御をスキップすることができます。これはgotoに近いと言えるでしょう。
また例外処理を使うことで、処理をスキップする意図も明確になります。逆に、gotoはそう言った意図が分からないからJavaで採用されなかったと言えます。
- システム
エンジニア - Javaではgotoが使えないのですね。
- プロジェクト
マネージャー - gotoは使えませんが、gotoと同様の効果があるラベル付きのbreakなどで代用ができることを理解しておきましょう。
Javaではgotoは使えないが、代わりの手段は沢山ある
Javaのgotoについて解説しましたが、ご理解頂けましたでしょうか。Javaではgotoは利用できませんが、ラベル付きのbreakやcontinue、try~catchの例外処理でgotoと同じことが出来ることが分かったと思います。
むしろそういった特定の機能を使った方がgotoより意図が明確になるので望ましいでしょう。Javaの設計思想が良く考えられていることがお分かり頂けたのではないでしょうか。
FEnetJava・Javaコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。


Java新着案件New Job
官公庁向け業務システム開発/Java/東京都千代田区/【WEB面談可】/テレワーク
月給39万~44万円東京都千代田区(永田町駅)販売管理システム開発/Java/東京都中央区/【WEB面談可】/テレワーク
月給49万~55万円東京都中央区(京橋駅)生命保険会社向けシステム開発/Java/東京都千代田区/【WEB面談可】/テレワーク
月給42万~48万円東京都千代田区(大手町駅)社会保険システムのパッケージ開発/Java/東京都港区/【WEB面談可】/テレワーク
月給42万~48万円東京都港区(新橋駅)金融機関向けシステム更改/Java/東京都江東区/【WEB面談可】/テレワーク
月給46万~51万円東京都江東区(豊洲駅)大手通信会社者向けWebシステム改修/Java/東京都港区/【WEB面談可】/テレワーク
月給42万~48万円東京都港区(品川駅)