Javaで条件文を書く方法

著者は、書くことで寄付金を集めるプログラムの一環として、フリー&オープンソース基金に寄付することを選びました。

はじめに

条件文はプログラムの流れを変えます。条件文は分岐文とも呼ばれます。条件が一致すると、コードの中の一つの枝に流れが進みます。条件が満たされない場合は、別の条件が評価されます(もしあれば)。この評価は、すべての条件が真または偽に評価されるまで続きます。例えば、以下の条件文を使って二つの数値(xとy)を比較することができます: x > y, x = y, x < y. もしxが1でyが2の場合、最後のx < y の条件文が真に評価されるまで、3回の評価が行われます。

条件式には2つのタイプがあります。最初のタイプは「もし」とその拡張である「もしそれ以外の場合」です。このタイプは広く使われています。2つ目のタイプは「スイッチ」で、より具体的で制限されています。

このチュートリアルでは、Javaで条件文を書き、各タイプの使用例、利点、欠点について学びます。

前提条件

このチュートリアルを実行するためには、以下が必要です:

  • An environment in which you can execute Java programs to follow along with the examples. To set this up on your local machine, you will need the following:Java (version 11 or above) installed on your machine, with the compiler provided by the Java Development Kit (JDK). For Ubuntu and Debian, follow the steps for Option 1 in our tutorial, How To Install Java with Apt on Ubuntu 22.04. For other operating systems, including Mac and Windows, follow the download options for Java installation.
    To compile and run the code examples, this tutorial uses Java Shell, which is a Read-Evaluate-Print Loop (REPL) run from the command line. To get started with JShell, check out the Introduction to JShell guide.
  • Familiarity with Java and object-oriented programming, which you can find in our tutorial, How To Write Your First Program in Java.
  • An understanding of Java data types, which is discussed in our tutorial, Understanding Data Types in Java
    .

文とブロックの違いを区別する

条件文が満たされ、実行フローが該当するコードのブランチに向かうと、このブランチは単一のステートメントまたはコードのブロックのいずれかである可能性があります。ステートメントとコードのブロックは異なる方法で処理されるため、それらを区別することが重要です。

文(ぶん)は、通常(つうじょう)1行(いちぎょう)で実行(じっこう)され、セミコロンで終了(しゅうりょう)します。例(れい)えば、以下(いか)の文を使用(しよう)して、”example”を出力(しゅつりょく)します。

  1. System.out.println(“example”);

 

Info

情報:このチュートリアルの例コードに沿って進めるために、ローカルシステム上でJava Shellツールを開くには、jshellコマンドを実行します。その後、jshell> プロンプトの後に追加してENTERキーを押すことで、例をコピー、貼り付け、または編集することができます。jshellを終了するには、/exitと入力してください。

この文は、例として文字列「example」を出力するために、println()メソッドを使用しています。指示がない限り、Javaはこの文を条件なしに実行します。

Note

注意:
文は通常、1行で書かれていることが多いですが、公式の規則では1行80文字より長い行は避けるべきです。
もし文が80文字を超える場合は、複数行に分割する必要があります。
また、ラムダ式などの場合、文を数行にわたって記述する方が便利で直感的です。
いずれにせよ、Javaでは文内の改行に構文上の要件はありませんので、新しい行で文を続けることができます。
このチュートリアルの例文の一部を書き直して、文を複数行に分けてみてください。

文をまとめて実行する際にブロックを使用しています。ブロックとは、開始括弧({)で始まり、終了括弧(})で終わる0個以上の文のグループです。前のコードを書き換えて、次のようにブロックの中に配置することができます。

  1. {
  2. System.out.println(“example”);
  3. }

 

上記のブロックでは、System.out.println(“example”);の前に4つのスペースが使用されています。これらの4つのスペースはインデントと呼ばれます。Pythonなど他のプログラミング言語とは異なり、Javaではインデントは必要ではなく、コードに影響を与えません。しかし、可読性を向上させるため、および慣例として、ブロック内の行は通常4つのスペースをインデントします。ほとんどのコードエディタは自動インデントをサポートしていますが、慣例はプログラミング言語やエディタ間で異なります。したがって、コードエディタがインデントをサポートしている場合は、Javaのコードを書く際には4つのスペースに設定されていることを確認してください。このチュートリアルでおすすめされているJshellは、自動的に4つのスペースをインデントとして設定します。

この場合、コードをブロック内に配置しても条件がないため、違いはありません。したがって、文がブロック内にあるかどうかに関わらず、例が表示されます。jshellで前の2つの例を実行すると、どちらの場合でも同じ出力が得られます。

Output

example

上記の出力は、印刷の例文がブロック内外で同じように機能することを示しています。

このセクションでは、文やブロックの作り方について学びました。次のセクションでは、ブロック内に条件文を追加します。したがって、ブロック内の文は一緒に実行され、条件によって実行されます。

単一の条件式を使用する

最も一般的に使用される条件文は、if文です。条件比較の結果が真または偽のブール値であれば、if文を利用することができます。if文は、最も単純な形では単一の条件となりますが、より複雑な構造を持つこともあり、後のセクションで使用します。

単一のif文は、単一の条件の下でコードを実行するために使用されます。条件付きで実行されるコードはブロック内に配置し、最初にif(ブール式)を置きます。式、つまり条件がtrueである場合にのみ、コードブロックが実行されます。式がfalseに評価される場合は、条件付きブロックコードはスキップされます。

この例では、2つの数字を比較するコードの断片を書きます。比較の結果に応じて、メッセージが表示されることがあります。以下の行をjshellに追加してください。

  1. int x = 1;
  2. int y = 0;
  3. if (x > y) {
  4. System.out.println(x + ” is bigger than “ + y);
  5. }

 

最初の2行で変数xとyを定義します。3行目は条件付き「もし (x > y)」で、xがyより大きいかどうかを比較します。比較は常に括弧内で行われます。

ブロックコードは、最初の開き中カッコ({)で始まり、閉じ中カッコ(})で終わります。ブロック内では、文がprintln()メソッドを使用してxがyより大きいことを表示します。この条件が真の場合にのみ、ブロックコードが実行されます。

jshellでこのコードを実行すると、以下の出力が得られます。

Output

x ==> 1 y ==> 0 1 is bigger than 0

出力の最初の2行は、xとyの値を確認しています。3行目では、1は0より大きいと読み取られており、条件式が真であることを意味しています。つまり、xはyよりも大きいです。もしxをyよりも小さく変えると、このメッセージは表示されなくなります。

条件文における最も重要なルールは、評価される式が真偽値に評価されなければならないということです。他のどの場合でも、比較しているものを真偽値に変換できないというエラーが発生します。

追加の練習として、ブール値ではない式でエラーを起こしてみてください。これを行うには、ブール値に変換できないint変数を条件の括弧内に配置します。

  1. int x = 1;
  2. if (x) {
  3. System.out.println(“Will this work?”);
  4. }

 

1行目では、int型の変数xを定義し、値(1)を代入します。2行目は条件式if (x)であり、xをブーリアンに変換することができないため、プログラムがクラッシュします。上記のコードをjshellで実行すると、以下のエラーが表示されます。

Output

x ==> 1 | Error: | incompatible types: int cannot be converted to boolean | if (x) { | ^

最初の行は、xが値1を受け取ったことを確認しています。次の行では、xのようなint値はboolean値に変換できないという互換性のない型のエラーが説明されています。このようなエラーが発生した場合は、比較を再確認する必要があることが分かるでしょう。

このような非ブール条件文は、条件文における最も一般的な落とし穴であるかもしれません。幸いなことに、現代のIDE(統合開発環境)は、書きながらこのようなエラーをキャッチしてくれます。それでも、IDEを使わなくても、エラーは比較的簡単に見つけることができます。

ブロックを使わずに条件文を書く

Javaのif文の特異な点は、コードブロックを使わずに短い形式で書く方法があることです。コードブロックなしで条件分岐をすることはおすすめされませんが、このような書き方も可能であることを知っておくべきです。実際のところ、Javaの試験の勉強や就職面接で、こんな混乱するような例に遭遇するかもしれないので、準備しておくべきです。

例えば、コードのブロックを使う代わりに、こんなふうにステートメントを書くこともできます。

  1. int x = 1;
  2. int y = 0;
  3. if (x > y)
  4. System.out.println(x + ” is bigger than “ + y);

 

前の例との違いは、条件文if(x > y)の後にコードのブロックがないことです。代わりに、対象の文「System.out.println(x + ” is bigger than ” + y)」が、条件文if(x > y)の直後にすぐに続きます。

このコードをjshellで実行すると、前の例と同じ出力が得られます。

Output

x ==> 1 y ==> 0 1 is bigger than 0

最初の2行には、xとyの値が表示されます。1が0よりも大きいことを確認するメッセージは3行目に表示されます。

条件に続くブロックコードがない場合、条件文の直後の行のみが条件に依存します。この場合、行4以降のステートメントは条件にかかわらず実行されます。例えば、xの値を0に変えて、yよりも大きくならないようにし、次のように5行目を追加してみてください。

  1. int x = 0;
  2. int y = 0;
  3. if (x > y)
  4. System.out.println(x + ” is bigger than “ + y);
  5. System.out.println(“This line is always printed.”);

 

上記のコードをjshellで実行すると、以下の出力が得られます。

Output

x ==> 0 y ==> 0 This line is always printed.

1行目と2行目にはxとyの値が印刷されます。両方の値は0であり、それは等しいことを意味します。そのため、条件文x > yはfalseを返します。したがって、xがyより大きいという4行目の文は印刷されません。しかし、条件に依存しないため、5行目は印刷されます。

また、5行目のインデント(字下げ)は不要です。それは5行目の実行が条件に依存していることを示すために含まれていましたが、実際にはそのような場合ではありません。このインデントは省略することもできますが、それによってコードがより明確になるわけではありません。

コードブロックなしで条件文を使用することは直感的ではなく、追いにくいため、略記法は控えめに使用するべきです。コードをきれいで理解しやすく保つために、ブロック文を使用する方が良いです。それらはより読みやすく、複数行の条件付きのコードを実行することができます。

入れ子のif文は、書くことは可能ですが通常は推奨されないコードの例です。次のセクションでは、入れ子のif文を探求して、その価値と欠点をよりよく理解します。

ネストされた条件分岐文

より複雑な条件構造を作成するためには、多くの if 文を組み合わせることが可能です。ネストされた if 文を作成するためには、コードブロックではなく親の if 文の中に別の if 文を配置します。

通常、コードを読みづらく理解しにくくするため、この方法は推奨されません。しかしながら、入れ子のif文には場合によっては実用的な用途があるため、理解していると役立ちます。

これがどのように行われるのか理解するために、前の例を拡張して、もう1つのif文を追加します。yを再び評価して0と等しいかどうかを比較します。次の行をjshellに追加してください。

  1. int x = 1;
  2. int y = 0;
  3. if (x > y) {
  4. if (y == 0) {
  5. System.out.println(“This is legal but does not look clean.”);
  6. }
  7. }

 

前の例から最初の3行は変わりません:int変数(xとy)を定義し、比較します。4行目では、もう1つのif文が、yが0と等しいかどうかを比較します。真の場合、Javaは5行目に進み、メッセージ「これは合法ですが、きれいに見えません」というprintln()文を実行します。

jshellでこれを実行すると、以下の出力が得られます。

Output

x ==> 1 y ==> 0 This is legal but does not look clean.

最初の2行は、xとyの値を確認しています。3行目は「これは正当ですが、きれいには見えません。」と読みます。このメッセージは、ブロックコードが実行されたことを確認しています。なぜならば、x > y と y == 0 の両方の条件が満たされているからです。

日本語での一つのオプションとして、次の文章を言い換えます:
このようにして、if文を無制限にネストすることができます。しかし、ネストされたif文が増えるごとに、コードの複雑さは高まり、読みやすさは低下します。そのため、if文のネストは一般的には良いプログラミングの慣習とはされていません。

ただし、入れ子になった条件付き構造は実用性があります。時には、可読性を犠牲にして複雑さを増すことで、より短いコードを書いて時間を節約することが価値があるように思われることもあります。その結果、試験や就職面接、現実世界の生産的なコードで入れ子の文が出てくることもあるでしょう。

以下は日本語でのパラフレーズです:
「拡張されたIf条件文を使って、Else If文やElse文を組み合わせてください。」

もし条件分岐を追加のマッチング条件で拡張したい場合は、else ifとelseを補足文として使用することができます。else文は最初のif文の後にのみ使用されます。 else ifを使用すると、最初のifと同様に無制限の追加条件文を追加することができます。最後のオプションのelseでは、前の条件文がマッチしなかった場合にプログラムフローが従うデフォルトのパスを指定します。

else ifとelseを使用することで、単一のif文よりもプログラムの流れをより多くの方向に分岐させることができます。したがって、他のどの方法でも構築することができない複雑な条件構造を構築することができます。コードをさまざまな方向に分岐させることで、より複雑なビジネスケースを扱うことができます。ただし、本番環境におけるビジネス要件は数多くあり、設計フローは必ずしも直感的ではないこともあります。

以下のコード例を使って、else ifとelseステートメントのアイデアを理解しましょう。以前使用したコードを拡張し、さらに条件分岐を追加します。これらの新しい条件式は、引き続きxとyを比較します。

  1. int x = 1;
  2. int y = 0;
  3. if (x > y) {
  4. System.out.println(x + ” is bigger than “ + y);
  5. } else if (x < y) {
  6. System.out.println(y + ” is bigger than “ + x);
  7. } else if (x == y) {
  8. System.out.println(x + ” is equal to “ + y);
  9. } else {
  10. System.out.println(x + ” cannot be compared to “ + y);
  11. }

 

上記のコードによると、1行目と2行目で変数xとyが定義され、それぞれの値が1と0になっています。3行目と4行目では、if文を使ってxがyより大きいかどうかを評価しています。もし評価が真であれば、「xはyより大きい」というテキストが表示され、条件付き構造から出ます。もし評価が偽であれば、プログラムは次の条件に進みます。これまでのコードは以前の例と同じです。

5行目のif文の閉じかっこの後に、else if文があります。これはif文と似た構文で、括弧内にブール式があり、その後にコードブロックが続きます。この式は、yがxより大きいかどうかを評価し、これは以前のif文とは逆の結果となります。もし式が真であれば、それに続くコードブロックが実行され、再び条件付き構造から抜けます。この場合、6行目の文がそれであり、yはxより大きいと出力されます。

7行目にはもう1つのelse ifの場合があります。この場合、括弧の中でxがyと等しいかどうかをチェックします。もし真であれば、8行目の文が実行され、xはyと等しいと表示されます。このようなelse if文は、条件を評価し、無制限に追加することができます。

9行目には最後のelse文があります。この文は常に最後にあり、条件を持たないため、他の条件文が一つもマッチしない場合には必ずこの文が実行されます。つまり、elseの後にあるコードブロックは、以前にif文やelse if文の条件が一つも満たされなかった場合に実行されます。もしこの文が真であるなら、10行目のコードが実行され、xはyと比較できないと表示されます。

複雑な条件文では最初の if 文だけが必要です。追加の比較を行いたい場合は、ゼロ個以上の else if 文を使用できます。最後に、他の条件文に一致しなかった場合にマッチするオプションの else 文を置くこともできます。

上記のコードをjshellで実行すると、以下の出力が得られます。

Output

x ==> 1 y ==> 0 1 is bigger than 0

上記の出力から、最初の行と2行目はxとyの値を確認しています。その値は、それぞれ1と0です。3行目では、1が0より大きいと出力されており、これによって論理式(x > y)がtrueを返し、その後のブロックコードが実行されたことが確認されています。

ifとelse if、elseの文を書くことは、複雑な条件構造を書く良い方法です。なぜなら、それぞれのif文やelse if文に異なる条件を置くことができます。上記の例では、最初にx > yを比較し、その後x < yの逆を比較し、最後にx == yを比較しました。このコードは、比較がわずかな場合でも読みやすく管理しやすいです。

しかし、さらに比較を行う必要がある場合は、もっと多くのelse if文を追加すると、コードが追いにくくなり、混乱する可能性があります。そのため、可能な限り構造を小さく単純にすることが重要です。さらに、一部の場合では、スイッチ文を使用すると、そのような複雑な構造の代替手段が存在します。次のセクションで使用します。

スイッチ条件を使用している

スイッチ文は、意思決定構造を構築するために使用できる別の条件文です。プログラムのフローを条件に基づいて制御するため、if文と似ています。ただし、スイッチ文は単一の変数と異なる予め定義されたケースとの一致を取り扱います。そのため、x > yのようなブール式を評価することはできません。代わりに、例えばint変数とその値を他のint変数と比較して一致するかどうかを判断します。一致(つまり、ケース)がある場合、プログラムのフローは一致に基づいてリダイレクトされます。

スイッチ条件には2つの重要なルールがあります。1つ目は、比較される変数が特定のデータ型のみであることです。プリミティブな型であるintやchar、および参照型であるStringやIntegerなどが該当します。(サポートされているデータ型の完全なリストは公式のスイッチのドキュメントで確認できます。)したがって、boolean型の変数は使用できず、スイッチ条件はif条件の代わりにはなりません。

もう一つの重要なルールは、case文の値はリテラルまたは定数である必要があるということです。定数は変数に似ていますが、定義されるときに前にfinalキーワードが付いています。変数とは異なり、定数の値を定義した後は変更することはできません。定数については、私たちのJavaシリーズの将来のチュートリアルで詳しく説明されます。

スイッチはif構文に比べて制限が多いし、完全に代替とはなりません。それでも、可読性が高く、比較が多い場合にはより適しているというユニークな利点があります。

たとえば、各月の数値表現(1から12まで)を月の名前と一致させたいと想像してみてください。if-else if構造を使用する場合、類似した12個の比較を行う必要があります。しかし、switchを使用すると、コードを繰り返すことなくより簡潔に処理することができます。

月のスイッチ条件を使った構文の練習をするために、以下の行をjshellに追加してください。年の月を数字で表すint変数と、各月の名前に対応するcase文があります。

  1. int monthOfYear = 1;
  2. switch (monthOfYear) {
  3. case 1:
  4. System.out.println(“January”);
  5. break;
  6. case 2:
  7. System.out.println(“February”);
  8. break;
  9. default:
  10. System.out.println(“Not a month”);
  11. }

 

1行目には、値が1の変数monthOfYearがあります。この変数はswitch文で使用されます。2行目には、switch文の定義があります。変数monthOfYearはかっこ内に配置され、比較されることが示されています。その後、さまざまなcase条件が記述されたコードブロックが始まります。

3行目に、値が1である最初のケースが来ます。最初の比較は、monthOfYearが1と等しいかどうかです。比較された値の後には必ずコロン(:)が続きます。4行目には、println()メソッドが来て、1がマッチした場合に、月の名前として「January」を出力することを示します。この行は、0以上の文または0行以上の文で構成されることがあります。つまり、省略することもできます。

最初のケースの後には、5行目においてブレーク文があります。このブレーク文によって、条件が満たされるとスイッチ条件構造から抜け出します。したがって、ブレークが実行されると、他のどのケース条件も評価されません。代わりに、プログラムの流れはスイッチ条件の終わりの括弧の後、この例では11行目に続きます。ブレークはオプションですので、忘れてしまうこともあります。その場合、一致するケースがあっても、スイッチは条件構造から抜け出すことなく、残りのケースの評価を続けます。これによって予期しない出力やデバッグが難しい問題が引き起こされる可能性があります。

次の場合の条件は、6行目、7行目、および8行目にあり、monthOfYearの値が2と一致するかどうかを確認します。これら3行は、前の3行と同じ構文を使用していますが、7行目では「2月」の新しい文字列が使用されています。簡潔にするため、残りの10ヶ月の場合の条件は省略されていますが、それらも各月の名前に新しい文字列を使用して同じ構造に従います。

9行目にはデフォルトのステートメントがあります。条件がないため、常にマッチします。これはオプションであり、以前にリストされたケースにマッチしない場合のプログラムの流れのデフォルトパスを定義するために使用されます。これは、if条件文のelseステートメントに似ています。

11行目には、条件文のブロックを終了するための閉じ括弧があります。

上記のコードを実行するには、jshellに貼り付けてください。次の出力が表示されます。

Output

monthOfYear ==> 1 January

最初の行は、monthOfYearの値が1であることを確認しています。2行目は「January」と出力するため、値1の場合に一致する条件分岐が行われています。つまり、monthOfYearが1であるため、次の行の文が実行されて「January」が出力されます。

練習として、monthOfYearの値を変更したり、もっと条件を追加したり、ブレークステートメントを削除して結果がどのように変わるかを理解するようにしてみてください。

結論

このチュートリアルでは、条件文を使用してプログラムの実行フローを制御しました。if文とswitch文をどんな場面で適切に使用するべきかを学び、それらを使ったいくつかのコード例も作成しました。また、クリーンなコードのためのベストプラクティスや、条件文に関連する一般的な問題を避ける方法も学びました。

Javaに関する詳細は、私たちの「Javaでのコーディング方法」シリーズを参照してください。

コメントを残す 0

Your email address will not be published. Required fields are marked *