トップ / カリキュラム / 第5章

CHAPTER 05

処理の流れ

プログラムは上から下へ順に実行されますが、それだけでは仕事になりません。「もし〜なら」で分かれ、「〜の間」繰り返し、「まとまった手順」を呼び出す。この3つで、業務のルールはほぼ表現できます。

読む目安:約20分条件分岐・繰り返し・メソッド

この章でわかること

  1. if・for・メソッド呼び出しが出てきたとき、処理の流れを追える
  2. 業務ルール(承認の条件、明細の合計など)がコードでどう表現されるか想像できる
  3. 「例外処理(try-catch)」が何のためにあるか説明できる

処理の流れは3種類しかない

どんなに複雑な業務システムでも、プログラムの流れは次の3つの組み合わせでできています。これは構造化プログラミングと呼ばれる考え方で、Javaに限らずほとんどの言語に共通します。

① 順次上から下へ順番に
② 分岐条件によって道が分かれる
if / switch
③ 繰り返し条件を満たす間、何度も
for / while
たとえ:業務マニュアルも同じ構造です。「手順1→手順2→手順3」(順次)、「金額が10万円以上なら部長承認へ」(分岐)、「明細がなくなるまで1行ずつ確認」(繰り返し)。コードはマニュアルを機械向けに書き直したものだと考えてください。

分岐:もし〜なら

if文は「条件が成り立つなら、このブロックを実行する」という指示です。経費精算の承認ルートを例にしてみます。

int amount = 150000;   // 申請金額

if (amount >= 100000) {
    System.out.println("部長承認が必要です");
} else if (amount >= 30000) {
    System.out.println("課長承認が必要です");
} else {
    System.out.println("担当者承認で完了です");
}
  • if (条件) { ... }条件が true(真)ならブロックの中を実行
  • else if (条件) { ... }上の条件が外れたとき、次の条件を確かめる。いくつでも続けられる
  • else { ... }どの条件にも当てはまらなかったとき
  • >=「以上」。比較に使う記号を比較演算子と呼ぶ

上から順に判定し、最初に当てはまったブロックだけが実行されます。15万円なら最初の条件に当てはまるので「部長承認」と表示され、残りは見ません。

記号意味記号意味
==等しい(= 1つは代入なので注意)!=等しくない
> / >=より大きい / 以上< / <=より小さい / 以下
&&かつ(両方成り立つ)||または(どちらか成り立つ)
!〜でない(否定)

文字列の比較は要注意

数値は == で比べられますが、文字列(String)は status.equals("承認済") のように .equals(...) メソッドで比べるのがJavaの決まりです。== で文字列を比べると「同じ内容なのに違うと判定される」バグの原因になります。Java初心者が最初に踏む有名な落とし穴です。

switch:選択肢が多いとき

「区分コードが A なら〜、B なら〜、C なら〜」のように、1つの値で何通りにも分かれるときは switch を使うと読みやすくなります。

String label = switch (taxType) {
    case "10" -> "標準税率 10%";
    case "08" -> "軽減税率 8%";
    case "00" -> "非課税・不課税";
    default -> "区分不明";
};

読んでみる:税区分コード taxType の値に応じて、表示用の文字列を label に入れている。default はどれにも当てはまらないとき。「->」を使う書き方は比較的新しい形式(Java 14以降)で、古いコードでは case "10": ... break; という形で書かれています。

繰り返し:〜の間、何度も

業務システムの中心は「大量のデータに同じ処理を繰り返す」ことです。これを担うのがループで、Javaでは主に for と while を使います。

// 請求明細の金額一覧(配列:同じ型の値を並べたもの)
int[] amounts = {120000, 80000, 130000};
int total = 0;

for (int a : amounts) {     // amounts の中身を1つずつ a に取り出して…
    total = total + a;      // 合計に足していく
}
System.out.println("合計:" + total);   // → 合計:330000
  • int[] amounts = {...}配列:同じ型の値を順番に並べた入れ物。[] が目印
  • for (int a : amounts)「amounts の要素を順に取り出し、1つずつ a と名付けて以下を実行」。拡張for文と呼ばれる
  • total = total + a;今の合計に a を足して、合計を更新。3回繰り返される

もうひとつ、昔からある書き方も見ておきましょう。コードを読んでいると頻繁に出会います。

for (int i = 0; i < 3; i++) {
    System.out.println((i + 1) + "件目を処理中");
}

読んでみる:カッコの中は「i を 0 から始め;i が 3 未満の間続け;1回ごとに i を 1 増やす(i++)」の3部構成。結果として中身が3回実行されます。プログラムの世界では数え始めが 0 なので、1件目・2件目と表示するために i + 1 しています。

while:回数が決まっていないとき

while (hasNextRow()) {      // 次の行がある間
    processRow();           // 1行処理する
}

「ファイルの最後まで」「未処理のデータがなくなるまで」のように、何回まわるか事前に分からないときは while を使います。条件が false になった時点で抜けます。

「バッチ処理」とは

月次締めや給与計算のような「夜間に大量のデータをまとめて処理する」仕組みをバッチ処理と呼びます。中身はまさに巨大なループで、1件ずつデータを読み、分岐で判定し、集計していく構造です。「バッチが途中で落ちた」と言われたら、この繰り返しの何件目かで想定外のデータに当たった、という状況が典型です。

メソッド:手順に名前を付けて再利用する

第3章で「メソッドは処理のかたまり」と学びました。ここでは、エンジニアがなぜメソッドに分けるのかを見ます。たとえば「税込金額を求める」計算が、請求書・見積書・領収書の3か所で必要だとします。同じ計算を3回書くと、税率が変わったとき3か所直さなければならず、直し忘れが事故になります。

// 税込金額を計算するメソッド。int型の値(税込金額)を返す
static int withTax(int price, int ratePercent) {
    return price + price * ratePercent / 100;
}

// 使う側(呼び出し)
int a = withTax(100000, 10);   // → 110000
int b = withTax(5000, 8);      // → 5400
  • static int withTax(...)メソッドの定義。int は「整数を返す」という戻り値の型。第3章の void は「何も返さない」だった
  • (int price, int ratePercent)引数(ひきすう):呼び出すときに渡してもらう値。2つ受け取る
  • return ...;計算結果を呼び出し元に返して、メソッドを終える
  • withTax(100000, 10)メソッドの呼び出し。渡した値が price と ratePercent に入り、結果が戻ってくる

メソッドは「何を受け取り(引数)、何を返すか(戻り値)」で性格が決まります。中身を知らなくても、この入口と出口が分かれば使えます。エンジニアが「このメソッドの仕様」と言うとき、多くはこの入口と出口の取り決めを指しています。

※ 実際の金額計算では第4章のとおり BigDecimal を使いますが、ここでは流れを見やすくするため int にしています。

例外処理:想定外に備える

最後に、業務システムのコードで必ず出てくる構文を紹介します。ファイルがない、数値のはずの欄に文字が入っていた、通信が切れた――こうした「想定外の事態」を、Javaでは例外(Exception)と呼び、try と catch で受け止めます。

try {
    int qty = Integer.parseInt(input);   // 入力を数値に変換(失敗するかもしれない)
    System.out.println("数量:" + qty);
} catch (NumberFormatException e) {
    System.out.println("数量には数字を入力してください");   // 失敗したときの対応
}
  • try { ... }「ここは失敗するかもしれない処理」と宣言した範囲
  • catch (〜Exception e) { ... }try の中で指定した種類の例外が起きたら、ここに飛んでくる。e には何が起きたかの情報が入る

例外処理のないプログラムは、想定外のデータ1件でその場で停止します。きちんと作られたシステムは、例外を受け止めて「エラーを記録し、その1件を飛ばして次へ進む」「処理をすべて取り消して(ロールバック)安全に止まる」といった対応をします。障害報告書に出てくる「〜Exceptionが発生」という文言は、まさにこの仕組みが「想定外を検知した」という記録です。

この章のまとめ

  • 処理の流れは「順次・分岐・繰り返し」の3種類の組み合わせ。業務マニュアルと同じ構造
  • if / else if / else は上から順に判定し、最初に当てはまった1つだけ実行。文字列の比較は .equals()
  • for と while で繰り返す。バッチ処理の正体は巨大なループ。数え始めは 0
  • メソッドは「引数を受け取り、戻り値を返す」手順書。入口と出口が分かれば中身を知らなくても使える
  • try / catch で想定外(例外)を受け止める。障害報告の「〜Exception」はこの仕組みの記録

確認クイズ

この章の内容を3問で確かめましょう。選ぶとすぐに解説が表示されます。

Q1. 次のコードで amount が 50000 のとき、何が表示されますか?
if (amount >= 100000) { A } else if (amount >= 30000) { B } else { C }

上から順に判定します。50000 は 100000 以上ではないので A は飛ばされ、30000 以上なので B が実行されます。当てはまった時点でそれ以降は見ません。

Q2. メソッドを使う側(呼び出す側)が、最低限知っていればよいことはどれですか?

メソッドは入口(引数)と出口(戻り値)の取り決めがあれば、中身を知らなくても使えます。これが処理を部品化する利点です。

Q3. 障害報告に「処理中に NumberFormatException が発生」とありました。この説明として最も近いものはどれですか?

「〜Exception」は実行中に起きた想定外の事態を表します。NumberFormatException は文字列を数値に変換できなかったときの例外です。コンパイルエラーとは別のものです。

読み終えたら、読了にしておきましょう。トップページのカリキュラムに記録が付きます(このブラウザ内だけに保存されます)。