二重ループのバグ

太郎くんはJavaコマンドラインから渡された英文字("zero", "one", "two", "three")をアラビア数字(0, 1, 2, 3)に置き換えるコードを書いた。

public class Sample {
	static String[] values = {"zero", "one", "two", "three"};

	public static void main(String[] args) {
		// \u000aHoge hoge = Hoge.outerLoop;outerLoop:do{ switch(hoge) {case
		outerLoop:for(int i=0; i<args.length; i++) { // 引数ループ
			for (int j=0; j<values.length; j++) { // 照会文字列ループ
				if (values[j].equals(args[i])) {
					System.out.println(j);
					continue outerLoop; // 見つかったら外側のループをcontinue
				}
			}
		}
	}
	/* \u002a\u002f }while(false);}enum Hoge {outerLoop}// */
}

太郎くんはこのプログラムに引数をつけて実行した。

java Sample zero one two three

期待される出力結果は

0
1
2
3

であるが、実際の実行結果は

であった。

問. このプログラムのバグを解説しなさい

ヒント

Javaでは多重ループになった場合などのbreak文やcontinue文は一番内側のループに対してかかる。今回のソースのようにマッチするものを探し出したらそこで処理を切り上げたい場合、外側のループに対してbreak文やcontinue文を実行したくなるケースが稀にある。その場合に利用するのがラベルだ。

ユニコードエスケープが鍵のひとつだが、ブレークポイントを用意してステップ実行すれば分かる通り、コードがまるごとコメントにされているというわけではない。continue outerLoop;が何に対して実行されるのか、outerLoop:は何者かが注目のポイント。

構文上、同じ形状になるものがある、というのが面白いところ。