System.out.println("Java学習中");

【Java / Spring Boot】UI/UXの視点を活かしたバックエンド開発の学習ポートフォリオ

【Java Silver対策】do-while文に潜むインデントの罠と条件式のひっかけ

Adobe Fireflyで作成

🟢 はじめに

今回は、Java Silverなどの試験でも超頻出のテーマと言われる

do-while文

に潜むひっかけポイントについて解説してみたいと思います。


🧭 今回のダンジョンコード

まずは、今回のコードを見てみましょう。

ある冒険者が、

1歩歩くごとにダメージを受ける「毒の沼地」

を歩いているコードです。

public class Main {
    public static void main(String[] args) {
        // --- ステージ1:安全な結界の部屋 ---
        int hpA = 10;
        do {
            System.out.println("冒険者AのHP: " + hpA);
            hpA -= 3; // 💥 ダメージを受ける
        } while (hpA > 0); // 💀 HPが0より大きければループ
        
        System.out.println("\n---- ステージ2の入り口 ----");
        
        // --- ステージ2:崩壊した結界の部屋 ---
        int hpB = 10;
        do
            System.out.println("冒険者BのHP: " + hpB);
            // hpB -= 3; // 👈 罠:コメントアウトで封印されている
        while ((hpB -= 3) > 0) ; // 👈 罠:こんなところで引き算が…
    }
}
「ステージ2の引き算(`hpB -= 3`)はコメントアウトされてるし、`while` の中で引き算してるから、画面に表示されるタイミングがズレて結果が変わるんじゃ…?」

そう思われた方も多いかもしれません。

実はこのコード、

ステージ1もステージ2も、画面に表示される結果はまったく同じ

になります。

なぜそうなるのか、順番に見ていきたいと思います。


🛑 {}(波カッコ)がない時

ステージ2のコードをよく見てみましょう。

do
    System.out.println("冒険者BのHP: " + hpB);
    // hpB -= 3;
while ((hpB -= 3) > 0) ;

綺麗にインデント(字下げ)されていて、いかにも

System.out...

と、

コメントアウトされた行

の2つが do の中身に見えますよね。

ですが、Javaの世界にはこんなルールがあります。

「do のあとに {}(波カッコ)がない場合、直後の1行(1命令)だけしか仲間に入れない」

つまり、コメントアウトを無視してコンピュータの視点で見ると、このコードの本当の姿はこうなっています。

do {
    System.out.println("冒険者BのHP: " + hpB); // 👈 doの仲間はこれだけ
} while ((hpB -= 3) > 0);

🎯 条件チェックの「関所」でコッソリ計算

「でも、ダメージを受ける処理(hpB -= 3)がコメントアウトされてるなら、HPが減らずに無限ループになるんじゃない?」

と思いますよね。

今回注目したいのは、

while の条件式の中に隠された (hpB -= 3) > 0 というコード

です。

なんと、

次の周回に行っていいか判定する「関所(条件式)」

の中で、

「HPを3減らしてから、0より大きいかチェックする」

という計算がコッソリ行われます。

この「冒険者B」の足跡を、1周ずつ追いかけてみましょう。


初期状態:hpB = 10

1回目(do

画面に

冒険者BのHP: 10

と表示します。

判定(while):関所に到着。

ここで (hpB -= 3) が発動して、HP7 に減ります。

7 > 0正しい(trueので、もう1周します。

2回目(do

現在のHP7 なので、

画面に

冒険者BのHP: 7

と表示します。

判定(while):また関所でHPが減って 4 になります。

4 > 0 なので、もう1周します。

3回目(do

現在のHP4 なので、

画面に

冒険者BのHP: 4

と表示します。

判定(while):また関所でHPが減って 1 になります。

1 > 0 なので、もう1周します。

4回目(do

現在のHP1 なので、

画面に

冒険者BのHP: 1

と表示します。

判定(while):また関所でHPが減って -2 になります。

-2 > 0false なので、ここでループ終了です。


🏁 答え合わせ

それでは、

ステージ1(冒険者A)とステージ2(冒険者B)の実行結果

を並べてみましょう。

冒険者AのHP: 10
冒険者AのHP: 7
冒険者AのHP: 4
冒険者AのHP: 1

---- ステージ2の入り口 ----
冒険者BのHP: 10
冒険者BのHP: 7
冒険者BのHP: 4
冒険者BのHP: 1
構造が違って見えた

のに、

出力されるタイミングも数値も完全に一致

しました。

Aは「部屋の中でダメージを受けてから関所へ行く」

Bは「部屋の中では何もせず、関所でダメージを受けてから判定する」

部屋の中で引くか、関所で引くか

の違いだけで、

「画面に表示したあとに、3減らして判定する」

という全体の流れが全く同じだったため、こんな不思議な結果になりました。


📝 まとめ

今回のコードから学べるポイントは以下の2つです。

{}がない時は直後の1行だけ

whileの中での計算は、その場で変数の値そのものが変わる

Java学習中の方の参考になれば幸いです🙌


【プロフィール・作品置き場】

kenichikamoi.com


🎵 Youtube(楽曲一覧)はこちら

www.youtube.com