ラベルを使うことにより、文には名前を付けられます。ラベルを参照できるのは、break文とcontinue文だけで、これらと組み合わせることで、反復処理を分かりやすく記述できる場合があります。
ラベルは次のように、名前を付けたい文の前に書き「:」を付けます。1つの文に対しては、1つのラベルだけ付けられます。
ラベル名: 文
先ほどの変数blackCountを使った例では「blackCount == 64000」という判定を、2カ所でしていて冗長でした。実はラベルを使うと、sample20.Sample09クラスで「// loop x」とコメントを付けた位置で、両方の反復処理を終了できます。
次のように、外側のfor文に「LOOP_RGBARRAY」という名前を付けておけば、内側のfor文内で「blackCount == 64000」のときに、LOOP_RGBARRAYからbreakできます。for文のところのみ抜粋します。
int blackCount = 0; LOOP_RGBARRAY: for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixel = rgbArray[y * width + x]; if (pixel == -16777216) { blackCount++; } if (blackCount == 64000) { System.out.println("break LOOP_RGBARRAY"); break LOOP_RGBARRAY; } Color c = new Color(pixel); int r = c.getRed(); int g = c.getGreen(); int b = c.getBlue(); System.out.print("("+x+","+y+")="+pixel+" "); } System.out.println(""); }
ちなみに、「break LOOP_RGBARRAY;」のようなbreak文は「ラベル付きbreak(labeled break)」といい、「break;」のようにラベルが付いていないbreak文は「ラベルなしbreak(unlabeled break)」といいます。このように、ラベル付きbreakを使うと、入れ子となっている反復処理からの終了を簡単に実現できるようになります。
最後に、ちょっとしたサンプルプログラムを紹介しておきます。少し前に、ネット上で話題になりましたが、画像データはHTMLで表現できます。当然、Javaでも画像データからHTMLを生成するプログラムを作れます。これまでの連載の内容を理解していれば、詳細な説明は必要ないと思います。コードを眺めて理解してみてください。
package sample20; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import javax.imageio.ImageIO; public class Sample11 { public static void main(String[] args) throws Exception{ String fileName = "rgb.png"; File imageFile = new File(fileName); BufferedImage image = ImageIO.read(imageFile); int width = image.getWidth(); int height = image.getHeight(); int[] rgbArray = new int[width * height]; int offset = 0; int scansize = width; image.getRGB(0, 0, width, height, rgbArray, offset, scansize); BufferedWriter writer = null; try { String encoding = "UTF-8"; writer = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(new File(fileName + ".html")), encoding)); writeHtml(rgbArray, width, height, writer); } finally { if (writer != null) { writer.close(); } } } private static void writeHtml(int[] rgbArray, int width, int height, BufferedWriter writer) throws IOException { writer.write("<html><head><meta http-equiv='content-type' "); writer.write("content='text/html;charset=UTF-8'></head>"); writer.write("<body style='padding:0px; margin:0px;font-size:xx-small;'>"); writer.write("<pre style='overflow: auto; white-space: pre-wrap;'>\n"); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int pixel = rgbArray[y * width + x]; Color c = new Color(pixel); int r = c.getRed(); int g = c.getGreen(); int b = c.getBlue(); writer.write("<span style='background-color: #"); writer.write(toHex(r, g, b) + "; color: #"); writer.write(toHex(r, g, b) + ";"); writer.write("'>■</span>"); } writer.write("\n"); } writer.write("</pre></body></html>"); writer.flush(); } private static String toHex(int r, int g, int b) { StringBuilder sb = new StringBuilder(); sb.append(Integer.toHexString(r/16)); sb.append(Integer.toHexString(r%16)); sb.append(Integer.toHexString(g/16)); sb.append(Integer.toHexString(g%16)); sb.append(Integer.toHexString(b/16)); sb.append(Integer.toHexString(b%16)); return sb.toString(); } }
今回は、拡張for文について説明をしました。拡張for文は、java.lang.Iterableインターフェイスを実装したクラスのオブジェクトや、配列のインスタンスの各要素に対してアクセスしたい場合に非常に便利ですし、コードの意図も分かりやすくなり、見やすくなりますから、どんどん活用するようにしましょう。
また、continue文、break文についても説明しました。これらを使うことにより、反復処理の流れを分かりやすく記述できます。また、ラベル付きのcontinue文やbreak文を使うことにより、入れ子の反復処理における処理の流れを分かりやすく記述できる場合があることも説明しました。これらの文法もよく使われるものなので、理解しておくようにしましょう。
サンプルプログラムでは、画像処理についても簡単ながら説明をしました。こういうプログラムを作ってみると、画像データは色の付いた点の集まりだということが実感できるはずです。たまには、こういったプログラムを作成して遊んでみるのもいいのではないかと思います。
次回は、列挙型について説明をする予定です。今回作ったサンプルのソースコードはこちらからダウンロードできます。
小山博史(こやま ひろし)
情報家電、コンピュータと教育の研究に従事する傍ら、オープンソースソフトウェア、Java技術の普及のための活動を行っている。長野県の地域コミュニティである、SSS(G)やbugs(J)の活動へも参加している。
著書に「基礎Java」(インプレス)、共著に「Javaコレクションフレームワーク」(ソフトバンククリエイティブ)、そのほかに雑誌執筆多数。
Copyright © ITmedia, Inc. All Rights Reserved.