Java入門 / Javaの構文

【Java入門】第13回 if文の利用(条件分岐)

2024.06.21

if文による条件分岐

プログラム上では、様々な判断とともに行うべき処理を切り替えるケースが非常に多くあります。

ここでは基本的な判断と処理の振り分けを行う方法として、if文の利用方法を紹介します。

キーワード(if・else・else if)

・if
 指定した条件式・真偽値が真かどうかの評価を行います。
 真であった場合だけ、後続に記述した処理を行います。

・else
 if条件の判定が偽であったとき別の処理を行う場合に記述します。  
 (elseの後続に記述した処理を行います)
 利用する場合は、if キーワードと必ず対で利用されます。

・else if
 if と else の間に記述され、複数個の判定条件を連結して、分岐の数を増やすことができます。
 前方で判定された条件式が偽であった場合のみ、次の条件判定を行います。

if文の構成

基本的な構成

if文による処理の分岐を行うには、ifキーワードに続けて括弧を記述し、括弧の中に評価する条件式を記述します。

Java
if( 条件式 )


括弧の中の条件式が真であった場合のみ、次のブロック内の処理、または次の1処理を行います。

① if条件に続けてブロックを記述した場合は、そのブロックの終わりまでの範囲の処理を行います。

Java
if( 条件式 ) {
  // 条件式が真の場合、後続のブロック内の処理を行う
  処理1;
}


② ブロックを設定しない場合は、次の1処理(次のセミコロン「;」までの処理)を行います。

Java
if( 条件式 ) 処理1;  //  直後の1処理(次の「;」まで)を行う


③ if条件の後に改行を行い、処理を次の行に記述した場合も②と同様です。

Java
if( 条件式 ) 
  処理1;  //  直後の1処理(次の「;」まで)を行う


上記のサンプル①~③では、どれも同じ処理結果(条件式1が真のとき、処理1が実行される)となりますが、if条件分岐時は、なるべく①のようにブロックを作成して「どの条件に合致したときの処理がどの範囲か」を明確することをお勧めします。

下記の例では、処理2は条件式の真偽に関わらず実行されます(処理1のみ、条件式の真偽もよって実行するかどうかがわかれます)が、パッと見では勘違いしてしまう可能性があります。

Java
if( 条件式 )
  処理1;
{
  処理2;  // 条件式の判定に関わらず必ず実行される
}

if条件① boolean値・変数

if文で判定する条件式は真偽値である必要があります。
boolean値はリテラル値、boolean型の変数、またはbooleanのラッパークラスであるBoolean型の変数は、if条件としてそのまま設定することが可能です。

値が偽(false)の時だけ実行したい場合は、条件として設定する変数の前に「!」(否定の演算子)を記述します。
また、Booleanのインスタンスを条件式として利用する場合は、nullではない必要があります。

Java
boolean bool = false;  // 判定条件のboolean変数
Boolean boolWrap = true;  // 判定条件のBooleanインスタンス

if( bool ) {
  // 変数bool が true の場合のみ処理
}

if( ! bool ) {
  // 変数bool が false の場合のみ処理
}

// Booleanクラス(booleanのラッパークラス)のインスタンス(null以外)も条件に指定可能
if( boolWrap ) {
  boolWrap
}

if条件② 条件式

条件式の部分には、真偽値の結果を返す式を記述することも可能です。

下記の例では、比較演算子(> や < など)を用いた式を、if文の条件式として設定しています。
(参考:第10回 Javaの演算子(比較演算子)

Java
int a = 0;  // 判定に用いるint値(1)
int b = 0;  // 判定に用いるint値(2)

if( a > b ) {
  // aがbより大きい場合の処理
}

if( a < b ) {
  // aがbより小さい場合の処理
}

if( a == b ) {
  // aとbの値が同じ場合の処理
}

if( a != b ) {
  // aとbの値が異なる場合の処理
}


booleanの値を返すメソッドを、条件式として利用することもできます。
下記の例では、引数が3より大きいかどうかを判定するメソッド「moreThan3」を作成して、if文の条件式として利用しています。

Java
public class IfWithMethod {
	/**
	 * mainメソッド
	 * @param args
	 */
	public static void main(String[] args) {
		
		int param = 10;
		
		if( moreThan3(param) ) 
			System.out.println("3より大きい値です");
		}
	}
	
	/**
	 * 3より大きいかどうかを返します
	 * @param p 3と比較するパラメータ
	 * @return パラメータが3より大きい場合はtrue、それ以外はfalse
	 */
	public static boolean moreThan3(int p) {
		return p > 3;
	}
}

合致しない場合の分岐(else)

if条件に合致した場合の処理に対し、条件に合致しない場合の処理も、else句を用い連結して記述することができます。
この場合、else句の前方に連結した条件式が全て偽であった場合にのみ、後続の処理を行います。

下記の例では、boolの値が偽(false)であるため、処理2だけが実行されます。
(逆に、もしboolの値が真(true)であった場合は、処理1だけが実行されることになります)

Java
boolean bool = false;  // 判定条件のboolean

if( bool ) {
  // 変数bool が true の場合の処理
  処理1;
  
} else {
  // 変数bool が false の場合の処理
  処理2;
  
}

異なる条件での分岐(else if)

Java
int a = 0;  // 判定に用いるint値(1)
int b = 1;  // 判定に用いるint値(2)

if( a > b ) {
  // aがbより大きい場合の処理
  処理1;
  
} else if( a + b > 0 ) {
  // a + b が 0 より大きい場合の処理
  処理2;
  
} else {
  // 「a > b」 でも 「a + b > 0」 でもない場合の処理
  処理3;
  
}


「else if」で条件を続ける場合、その前に記述した条件が全て偽となる場合だけ、条件判定されることに注意してください。

下記の例では、条件式1( x % 2 == 0 )の判定と、条件式2( x % 3 == 0 )の判定を、異なるif条件として準備しています。
この場合は、どちらの判定も必ず行われ、真の時はそれぞれの処理を行います。

Java
int x = 6;

if( x % 2 == 0 ) {
  // xが2で割り切れる場合の処理
  System.out.println( x + "は2で割り切れます。");
  
}

if( x % 3 == 0 ) {
  // xが3で割り切れる場合の処理(2で割り切れるかどうかは問わない)
  System.out.println( x + "は3で割り切れます。");
  
}


実行結果:

PowerShell
6は2で割り切れます。
6は3で割り切れます。


対して下記の例では、条件式1( y % 2 == 0 )が真であった場合、else if句で連結された条件式2( y % 3 == 0 )の判定は行われません(後続の処理も行いません)。

Java
int y = 6;

if( y % 2 == 0{
  // yが2で割り切れる場合の処理
  System.out.println( y + "は2で割り切れます。");

} else if( y % 3 == 0 ) {
  // yが2で割り切れない(elseの前の条件式が偽)、かつ、yが3で割り切れる場合の処理
    System.out.println( y + "は2で割り切れます。");
    
}


実行結果:

PowerShell
6は2で割り切れます。


また、else if で複数の条件を連結して記述することで、いずれかの条件式が真となるまで連続して判定することができます。
この場合、いずれかの条件式が真となったら、以降に連結されている判定や処理は行われません。

複数の条件を連結した場合も同様に、前方の条件判定が全て偽であった場合のみ、後続の条件判定および、else以降に記述された処理が実行されます。

Java
if( 条件式1 )
{
  // 「条件式1が真」の場合に処理する
  処理1;
  
} else if ( 条件式2 ) {
  // 「条件式1が偽」かつ、「条件式2が真」の場合に処理する
  処理2;
  
} else if ( 条件式3 ) {
  // 「条件式1~2が全て偽」かつ、「条件式3が真」の場合に処理する
  処理3;

} else if ( 条件式4 ) {
  // 「条件式1~3が全て偽」かつ、「条件式4が真」の場合に処理する
  処理4;

} else if ( 条件式5 ) {

    ... 中略(条件式5~8) ...

} else if ( 条件式9 ) {
  // 「条件式1~8が全て偽」かつ、「条件式9が真」の場合に処理する
  処理9;
  
} else {
  // 前方の条件式(条件式1~9)が全て偽の場合に処理する
  処理0;
  
}

複数条件の同時判定

複数の条件式を同時に判定したい場合は、論理演算子を利用して判定を行うことができます。
(参考:第10回 Javaの演算子(論理演算子)

「全て真」の判定(&&、&)

複数の条件を全て満たす必要がある場合は "&&"(または "&")の両側に条件を記述します。

条件式は演算子の左辺から順に評価されます。(3個以上連結した場合も同じです)

Java
if( 条件式1 && 条件式2 ) {
  // 条件式1が真、かつ、条件式2が真 の場合の処理
}

「いずれかが真」の判定(||、|)

複数条件のうち最低1つが条件を満たせばよい場合は、" || "(または " | ")の両側に条件を記述します。

こちらも同様に演算子の左辺から順に評価されます。

Java
if( 条件式1 || 条件式2 ) {
  // 条件式1が真、または、条件式2が真 の場合の処理
}

ショートサーキット(短絡評価)

ショートサーキット(短絡評価)とは

複数の条件式をつなぐ論理演算子は、2個つなげて記述する場合("&&"、" || ")と、1つしか記述しない場合("&"、" | ")がありますが、これはプログラムの動作に差があります。

"&&" と " || " の場合、条件が成立する/しないが判別された時点で、演算子以降(右側)の条件式の評価は行いません。(簡単に言えば「結果が確定したら残りは評価しない」動作となります)

Javaではこの「結果の判定に不要となった評価を行わない」動作をショートサーキット(短絡評価)と呼びます。

Java
boolean boolFalse = false;
boolean boolTrue = true;

if( boolFalse && boolTrue ) {
  // 1つ目の条件式(boolFalse)で、このifの条件が成立しないと判断できる
  // してもしなくても結果は一緒なので、2つ目の条件式(boolTrue)の評価は省略
}

if( boolTrue || boolFalse ) {
  // 1つ目の条件式(boolTrue)で、このifの条件が成立することと判断できる
  // これも2つ目の条件式の評価は不要になるので省略される
}


対して、1個しか記述しない場合は、演算子の前(左側)の条件式の結果にかかわらず、演算子の両側の条件式を評価します。(ショートサーキットなし)

"&&" と "&" の場合

論理積の演算子を2個重ねた場合と1個だけ記述した場合では、実際のプログラムの動作にどのような差が生じるでしょうか。

以下のサンプルプログラムを実行して確認してみます。

Java
/**
 * ショートサーキット(&&)確認用クラス
 */
public class ShortCircuitAmp {

	/**
	 * mainメソッド
	 * @param args
	 */
	public static void main(String[] args) {
		String msg = null;

		// ショートサーキット( & 2個)
		if( msg != null && msg.length() > 0 ) 		{
		  System.out.println("1.msgの文字数:" + msg.length());
		  
		} else {
		  System.out.println("1.msgは空です");
		  
		}

		// ショートサーキット無し( & 1個)
		if( msg != null & msg.length() > 0 ) {  // msg.length() > 0 も評価される
		  System.out.println("2.msgの文字数:" + msg.length());
		  
		} else {
		  System.out.println("2.msgは空です");
		  
		}
	}
}


実行結果:

PowerShell
1.msgは空です
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "msg" is null
	at ShortCircuitAmp.main(ShortCircuitAmp.java:23)


1つ目の条件式(msg != null)がfalseだった時点で条件を満たさないことが判定できるため、ショートサーキット有りの場合は2つ目の条件式(msg.length() > 0)の評価を行わず、すぐにelse句の後続ブロックに記述された処理が実行されていることがわかります。
(18行目の「1.msgは空です」を出力)

対してショートサーキット無しの部分では、2つ目の条件式も評価されてしまい、例外(NullPointerException)が発生して実行時エラーとなってしまいます。

" || " と " | " の場合

同じように、論理和についても下記のサンプルプログラムで動作を確認してみます。

Java
/**
 * ショートサーキット(||)確認用クラス
 */
public class ShortCircuitPipe {

	/**
	 * mainメソッド
	 * @param args
	 */
	public static void main(String[] args) {
		String msg1 = "Hello";
		String msg2 = null;

		// ショートサーキット( | 2個)
		if( msg1.length() > 0 || msg2.length() > 0 )
		{
			System.out.println("1.どちらかのメッセージは空ではありません");
		}
		else
		{
			System.out.println("1.メッセージはどちらも空です");
		}

		// ショートサーキット無し( | 1個)
		if( msg1.length() > 0 | msg2.length() > 0 )
		{
			System.out.println("2.どちらかのメッセージは空ではありません");
		}
		else
		{
			System.out.println("2.メッセージはどちらも空です");
		}
	}
}


実行結果:

PowerShell
1.どちらかのメッセージは空ではありません
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "msg2" is null
	at ShortCircuitPipe.main(ShortCircuitPipe.java:25)


1つ目の条件式(msg1.length() > 0)がtrueだった時点で条件を満たすことが判定できるため、ショートサーキット有りの場合は2つ目の条件式(msg2.length() > 0)の評価を行わず、すぐにif 条件の後続ブロックに記述された処理が実行されていることがわかります。
(21行目の「1.どちらかのメッセージは空ではありません」を出力)

また、こちらもショートサーキット無しの場合は2つ目の条件式が評価され、実行時エラーとなっています。

論理演算子の動作まとめ

論理演算子で複数の条件式をつなげて評価した場合の動作は、以下の表のとおりとなります。

演算子短絡評価動作
      
&&
1つでも偽(false)であった場合、すぐに全体を偽(false)と評価して、以降の条件式の評価を行わない。

&
×1つでも偽(false)であった場合、全体を偽(false)として評価するが、記述された条件式は全て評価する。

||
1つでも真(true)であった場合、すぐに全体を真(true)と評価して、以降の条件式の評価を行わない。

|
×1つでも真(true)であった場合、全体を真(true)として評価するが、記述された条件式は全て評価する。

排他的論理和と複数条件

第10回(Javaの演算子)でも説明したとおり、複数の真偽値については、排他的論理和( ^ )でも両辺の値から評価することができます。
このため、if文でも "&" や " | " と同じように、" ^ " でも複数の条件式をつないで同時に評価することが可能です。

ただ、排他的論理和の結果が直観的ではないことや、使用しなくても同じ条件判定ができるため、あまり一般的には利用されません。

このため、ここでは覚えなくても差し支えないと思いますので、排他的論理和の評価内容については、以下の欄内に参考として記載しています。
興味のある方は、下記の欄を開いて確認してみてください。

※参考: 排他的論理和( ^ )による複数条件の判定について

排他的論理和を複数の条件式に対して利用する場合は、他の論理演算子と同様に演算子の左右に条件式を記述します。

Java
boolean bool01, bool02;

if( bool01 ^ bool02 )
{
  // bool01、bool02 が「片方だけ真」の場合の処理
}


bool01とbool02の値と、排他的論理和を用いた条件式(bool01 ^ bool02) の評価結果は以下の表のとおりです。どちらか1個だけが真(true)の時だけ、排他的論理和も真となります。

bool01 ^ bool02bool01bool02
falsetruetrue
truetruefalse
truefalsetrue
falsefalsefalse


排他的論理和を利用しない場合でも、どちらか1つだけが真であることを判定したい場合は、論理積(&&)、論理和( || )、否定( ! )を利用して以下のように記述できます。

Java
boolean bool01, bool02;

// 「bool01が真、かつbool02が偽」または「bool01が偽、かつbool02が真」で判定
if( (bool01 && ! bool02) ||  ( ! bool01 && bool02) )
{
  // bool01、boole02の「片方だけ真」の場合の処理
}


排他的論理和を利用するよりも長くなってしまいますが、判断したい内容はこちらの方が具体的に表現できているのではないかと思います。

また、排他的論理和は「どちらか片方だけが真」であることを評価しますので、必ず演算子の両辺の条件式を評価しないと全体の判定ができません。(片方だけでは結果が絶対に確定しない)

このため、排他的論理和を論理演算子として記述する場合でも、ショートサーキットは存在しません。

株式会社GSI 採用サイト