対話型AIにアドバイスを受けながら進めるJavaプログラミングの入門連載。今回は、プログラムの実行の流れをコントロールする制御構文について、まずは条件分岐を学習します。その最も基本となるif文とswitch文を、条件式を作る際の考え方とともに理解しましょう。また、これらのより簡潔な書き方である条件演算子とswitch式も紹介します。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
本連載のサンプルコードをGitHubで公開しています。こちらからダウンロードしてみてください。
対話型AIにアドバイスを受けながら進めるJavaプログラミングの入門連載「AIアシスト時代のJavaプログラミング入門」。前回は、対話型AIのGitHub Copilot(以降、Copilot)を導入し、質問やコード補完を通じて、変数、データ型、演算子といったJavaの基本中の基本を学習しました。今回も、その流れでJavaを学んでいきます。前回は、最も入口の質問として、「Javaを勉強しようと思うんだけど、何から学べばよい?」と投げました。その回答の2番目に出てきた「制御構文:if-else, switch, for, while」を思い出してください。今回のテーマは、この「制御構文」です。
制御構文というと、その字面から難しそうな印象を受けます。前回のテーマの一つだった変数はデータの入れ物で、それにはデータ型があって、演算子で計算できるというのは、意外と直感的です。「では制御構文は?」というとピンと来ないことがあるでしょう。そこで、AIに聞いてみましょう。「Javaの制御構文ってどんなときに使う?」と投げてみました。長々と回答されますが、注目すべき内容は図1の「2.制御構文を使う場面」です。
ここには制御構文が3つ示されていて、それを使う場面が提示されています。
それぞれ、役割が違うのですね。「ジャンプ構文とか何だろう?」という疑問も湧くと思いますが、それらについては「繰り返し処理」とともに後続の回で取り上げていくとして、今回は1番目の「条件分岐」を掘り下げていきましょう。
図1の最後に「制御構文を使うことで、プログラムの柔軟性と効率性が向上します!」とあります。なぜ、制御構文を使うと柔軟性と効率性が向上するのでしょうか? ちょっと難しい回答が返ってくるかもしれませんが、聞いてみると面白いかもしれませんよ!
質問「Javaの制御構文ってどんなときに使う?」の回答に戻ると、「1.制御構文の種類と用途」に条件分岐についての説明がありました(図2)。
これによると、条件分岐には、if-else文とswitch文があるようです。説明自体は、「条件に応じて異なる処理を実行します。」などというように非常にシンプルなので、ここを新たな質問で掘り下げてみましょう。「条件分岐構文について、新しいものも含めて教えて。」と投げてみました(図3)。ここで「新しいものも含めて」と追加したのは、そうでない場合の回答が非常に基本的なものに限定されることが多いと考えるからです。Javaに限らず、プログラミング言語は日々進化しています。最新の構文を使えれば、コーディングが楽になったりシンプルに記述できたりなどのメリットがあるので、後学のためにも押さえておきましょう。
回答は、先頭から順番に見ていってもよいのですが、「まとめ」などに最初に目を通しておくとよい場合もあります。「どの情報に注目すべきか?」があらかじめ分かって、自身の知識などに応じて読むべきポイントが絞り込みやすくなるからです。まず、「まとめ」を以下に抜き出してみました。
基本的な構文があって、それらに簡潔な記述があり、モダンな方法もあるということが伝わってきます。そうすると、まずは基本構文を押さえて、理解したところで簡潔な記述に進み、モダンな方法は余裕があれば、という感じに学習を進められそうです。
そこで、図3の「7.条件分岐の使い分け」にある「if-else」から「新しいswitch式」までを、まずは見ていくことにしましょう。
ここではサラッと流しましたが、「モダンな方法」の「モダン」って何でしょうか? そもそもプログラミング言語ってモダン(現代的、近代的)なものですね。それでもあえて「モダン」を強調する理由は何かと聞いてみると、プログラミング言語のトレンドが伝わってくるかもしれませんよ。
if-else文は、図4の「1.基本的な条件分岐構文」にあります。
2つのパターンが示されています。それぞれ、抜き出してみました。
「if-else文」と「else if文」というように、なんだか似ていますね。ifとelseを書く順番を逆にしただけのように見えますが、何が違うのでしょうか?
if-else文は、条件が成立したときに何かをしたい、あるいは不成立のときに何かをしたい、というときに使います。例えば「点数が80点以上だったら合格とする、そうでなければ不合格とする」といったケースです。このように、分岐先が2つ用意されているときに使うわけですね。
構文と例は、既に図4の回答中に示されているので、それを見ればif-else文の書き方が分かります。せっかくなので、前回も使用した「コード補完」の機能を使って、上記のケースのコードを示してもらいましょう。今回用に、プロジェクトbranchを作成してください。プロジェクトの作り方を忘れてしまった人は、第1回を参照してください。
コード補完してもらうには、macOSでは[Command]+[I]、Windowsでは[Ctrl]+[I]をそれぞれエディタ上で入力するのでした。このあたりは、第2回で実践しましたね。あらかじめ、入力したい場所にカーソルを移動させておくのを忘れないでください。
質問文を入力すると、具体的なコードが提示されるので、[同意する]をクリックして確定させます(図5)。
確定させたら、実行してみましょう。「合格」と表示されれば成功です(図6)。ここでは「点数」に相当する変数にscoreを使っているので、scoreをいろいろな数値に変えて(特に、80未満にするなど)、実行結果がどう変わるか確認してみましょう。
なお、回答には示されていませんが、「条件が成立したときにだけ何かをする」といった記述もできます。この場合は、elseより後を書きません。「雨が降っていたら洗濯物を取り込む、そうでなければ何もしない」といったケースです。ifとelseを両方書く場合、ifだけの場合があると覚えておきましょう。
if-else文は、せいぜい分岐先が2個という場合に使いますが、もっと多くの分岐先が必要な場合には、else if文を使います。例えば「点数が90点以上だったら優、80点以上だったら良、70点以上だったら可、それ以外は不可とする」といったケースです。図4の回答にある構文と例を見ると、if-else文のelseの方にさらにif-else文を重ねていくというイメージですね。
こちらも、コード補完で上記のようなケースをコードにしてもらいましょう。もう、何をすればよいか分かりますね(図7)。
こちらも、変数scoreをいろいろな数値に変えて、実行結果がどう変わるか確認してみてください(図8)。
条件分岐をはじめ、制御構文はプログラムの流れを変える役割を持っています。このため、文章やサンプルコードだけでは直感的に理解しにくいところがあります。こういったときには図解が有効だと思うので、Copilotに「if文の構造を図で見せてください。」と投げて図解してもらうことにしました(図9)。
いつもより時間はかかり、あくまでもテキストベースですが、図解を試みてくれます。しかしながら、期待するものとは少し違うようです。条件「分岐」というくらいなので、道筋が2つできそうですが、一本道に見えますね。条件判断を2回行うように誤解されそうです。このように、現時点のCopilotでは図の制作ではまだまだ成長の余地がありそうです(Copilotで使うLLMを変更するなどで改善するかもしれませんが、本連載の主旨から外れるので省略します)。
図10と図11は、「フローチャート」という手法でif-else文とelse if文を表現したものです。
ここでは、Copilotの回答に沿って、if-else文、else if文と分けて解説しましたが、これらをまとめて「if文」としてしまうことがあります。if文の中に、else文やelse if文があるという感じです。あくまでも分類や言葉遣いの問題なので、理解することは変わりません。
ここまでif-else文を見てきましたが、たびたび「条件」というキーワードが登場しました。「○○以上」といった日本語で条件を表現するのは簡単ですが、Javaではどのように表現するのでしょうか? 図5のように「score >= 80」とあるのがそれっぽいですが、どのような書き方があるのか、Copilotに聞いてみましょう。「if-else文の条件の書き方は?」と投げてみました(図12)。
ここでも、「まとめ」から見てみましょう。if-else文やelse if文の説明も混じっていますが、1番目の「ifの条件には、比較演算子や論理演算子を使って評価式を記述します。」と大事なことが書かれています。つまり、条件は、比較演算子や論理演算子を組み合わせて「評価式」として記述するということです。比較演算子と論理演算子については、第2回で紹介済みですね。では、ここで改めてこれらの演算子について見てみましょう。「条件の書き方」の「(1)比較演算子」です(図13)。
内容としては、第2回の表6にまとめたものと同じです。「==」などの記号で、「等しい」「等しくない」などを比較します。数学で使う演算子とは微妙に異なりますが、あくまでも書き方の問題で、考え方は同じです。比較演算子により、同じであるかどうか、大小などを判定できます。
続けて論理演算子です(図14)。
こちらも、内容としては、第2回の表7にまとめたものと同じです。ただし、一部正しく表示されていないので(論理和に相当すると思われる箇所です)、このあたりは別途聞いてみるか、資料で調べてみるとよいでしょう。
論理演算子は、複数の比較演算子の結果を「かつ」「または」で結合するか、単一の比較演算子の結果を「でない」で反転するものです。例えば前者で言えば、「0から100であれば有効、そうでない場合は無効」といったケースです。「0から100」というのは、比較演算子だけでは表現できません。「0 <= score <= 100」とは書けないのです。論理演算子を使うことで、このような条件を表現することができます。
図14には論理演算子の例がなかったので、コード補完で上記のようなケースのコードを示してもらいましょう(図15)。0以上(>=)で、かつ、100以下(<=)という2つの条件を「&&」で組み合わせて、全体の条件としています。
変数scoreを負数にしたり、100を超える値にしたりして、いろいろ試してみてください(図16)。
Copilotの回答では特に言及されていなかった「if (...) { ... }」の「{ ... }」とは何でしょうか? 必ず書かなければならないのか、書かなくてもよいケースがあるのか聞いてみると、if-else文の理解を深められるかもしれませんよ!
続けて、switch文です。if-else文があるのにswitch文というのが別にあるからには、if-else文にはない特徴がありそうです。「条件分岐構文について、新しいものも含めて教えて。」の回答の該当箇所「2.switch文」を見てみましょう(図17)。
例を見ると分かりますが、switch文では、変数の値の候補を「case 値:」で書いていき、一致したところの文が実行されるという仕組みになっています。「同じようなことはelse if文でも書けるのでは?」という疑問が湧くかもしれませんが、switch文を使うともっとシンプルに書くことができます。例では数値を曜日として表示していましたが、「月から日数を得る」ようなコードもswitch文で書くことができます。コード補完で試してみましょう(図18)。
このコードでは月を変数monthで指定しているので、2月以外の数値を指定して結果がどう変わるか試してみましょう(図19)。
図18では、「case 1:」といった記述が幾つもつながっていることに注目してください。このように、複数の「case xx:」をつなげれば、「そのいずれか」に相当する条件とできます。このような条件をif-else文やelse if文で書くと大変そうですね。また、見慣れない「break;」という文がありますが、これはswitch文を終えるための文です。breakがないと、次の文が実行されてしまうので注意が必要です。また、全ての「case xx:」に一致しない場合の「default:」も必要です。
caseとかbreakとかdefaultとかキーワードが多くて混乱しそうですが、理解するよりもswitch文を使う上でのお約束として覚えておくのがよいです。
switch文は、if-else文で書くと条件が複雑になってしまうような場合に有用です。図18のコードをif-else文で書き直すとどのようになるか、Copilotに聞いてみましょう。もちろん、自身でやってみても構いませんよ!
ここまでで、基本構文とされるif-else文(else if文)とswitch文を学習しました。今回最後は、図3「まとめ」の2番目「簡潔な記述」とされている三項演算子とswitch式です(図20)。
if-else文とswitch文があれば、たいていの条件には対応できます。ただし、時として「やりたいことに比べて、記述の必要なコードが多い」というようなケースがあります。例えば図20の例では、条件である「数値が5以上か、あるいは5未満であるか」を判定して、それぞれに応じたメッセージを表示しています。これは、図20の三項演算子の例のように、「条件式? 成立時のメッセージ:不成立時のメッセージ」として必要なメッセージだけ計算させて、それを表示するだけというようにシンプルにできます。「条件A? 成立時B:不成立時C」という3つの項目が絡むので、ここでは「三項演算子」としましたが、一般には「条件演算子」と呼ばれます。
また、図20のswitch文の例は、同じく図20のswitch式の例のように、値に応じた曜日名をだけ計算させて、それを表示するだけというようにシンプルにできます。switch文と違うのは、あくまでもswitch式は「式」であり、何らかの値を最終的に返すという点です。また、「case xx:」ではなく「case xx ->」と記述しますし、breakが不要な点も違いますね。
こう見ると、switch式はswitch文にあった約束事が変わっていることに気付きます。なぜそのようになったか聞いてみると、「モダン」の片りんが感じられるかもしれませんよ!
今回は、プログラムの流れをコントロールする制御構文の一つである条件分岐(if-else文、switch文など)を、条件式と併せてCopilotに聞きながら学習しました。
次回は、制御構文のもう一つの重要機能である、繰り返しを学習します。
WINGSプロジェクト 山内直
WINGSプロジェクト所属のテクニカルライター。出版社秀和システムを経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。
・たまデジ。 | たまプラーザで生活、仕事する。(https://naosan.jp/)
WINGSプロジェクト
有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティー(代表山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手掛ける。2021年10月時点での登録メンバーは55人で、現在も執筆メンバーを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。
・サーバーサイド技術の学び舎 - WINGS(https://wings.msn.to/)
・RSS(https://wings.msn.to/contents/rss.php)
・X: @WingsPro_info(https://x.com/WingsPro_info)
・Facebook(https://www.facebook.com/WINGSProject)
Copyright © ITmedia, Inc. All Rights Reserved.