if文は、Javaの基本的な制御フロー構造で、ブーリアン条件に基づいて異なるコードブロックを実行することができます。述語x > 5がtrueと評価されると、if節の文が実行され、xが5より大きいという文字列を出力するという例を見てみましょう。
int x = 8;
if (x > 5) {
System.out.println("x is greater than 5");
}
さらにオプションで、論理式が偽と評価された場合に実行される追加のステートメントを含むelse節を追加することもできます。
int x = 10;
if (x > 5) {
System.out.println("x is greater than 5");
} else {
System.out.println("x is not greater than 5");
}
この例では、述語x > 5がtrueと評価されると、if節の文が実行され、"x is greater than 5"という文字列が出力されます。もし論理式がfalseと評価されると、else節の文が代わりに実行されます。
また、if-else文では、if節とelse節を複数使うことで、複数の条件を連鎖させることができます。
int z = 8;
if (z > 10) {
System.out.println("z is greater than 10");
} else if (z > 5) {
System.out.println("z is greater than 5 but not greater than 10");
} else {
System.out.println("z is not greater than 5");
}
この場合、最初の述語z > 10はfalseと評価されるため、最初のif節内のコードブロックはスキップされます。2番目の述語z > 5はtrueと評価されるので、2番目のif節内のコードブロックが実行され、"z is greater than 5 but not greater than 10"という文字列が出力されます。もし両方の述語がfalseと評価されたら、else節内のコードブロックが実行されるはずでした。
連鎖したif-else文のif節とelse節の順序は重要です。if節とelse節の真偽値式は、出現した順に評価され、最初に真と評価された真偽値式は対応するコードブロックを実行させ、残りの真偽値式は評価されません。たとえば、次のような連鎖した if-else 文を考えてみましょう。
double grade = 87.5;
if (grade >= 90) {
System.out.println("A");
} else if (grade >= 80) {
System.out.println("B");
} else if (grade >= 70) {
System.out.println("C");
} else if (grade >= 60) {
System.out.println("D");
} else {
System.out.println("F");
}
この例では、最初の述語grade >= 90はfalseと評価されるので、最初のif節内のコードブロックはスキップされます。2番目の述語grade >= 80は trueと評価されるので、2番目のif節内のコードブロックが実行され、出力はBとなります。
ブール式は表示された順に評価されるので、望ましい動作を得るためには正しい順序で並べることが重要であることを心に留めておく必要があります。たとえば、ブール式をこのように並べ替えたとしましょう。
double grade = 87.5;
if (grade >= 60) {
System.out.println("D");
} else if (grade >= 70) {
System.out.println("C");
} else if (grade >= 80) {
System.out.println("B");
} else if (grade >= 90) {
System.out.println("A");
} else {
System.out.println("F");
}
この場合、最初のブール式grade >= 60が真と評価され、対応するコードブロックが実行されるため、gradeが実際にはBよりも高いにもかかわらず、出力はDとなります。
Javaの制御フローでString型を比較するときは注意が必要です。等号演算子==や!=で比較できるintやdoubleなどの基本型とは異なり、JavaのStringオブジェクトはequals()メソッドで比較しなければなりません。等号演算子==と!=は、オブジェクトの値ではなく、オブジェクトへの参照を比較します。
public class Main {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = new String(s1);
if (s1 == s2) {
System.out.println("The strings are equal");
} else {
System.out.println("The strings are not equal");
}
}
}
この場合、オブジェクトの値は同じでもs1とs2オブジェクトへの参照を比較しているため、==演算子はfalseを返します。この場合の出力は、"The strings are not equal"となります。
この問題を避けるために、JavaでStringオブジェクトを比較するときは、常にequals()メソッドを使用することをお勧めします。
public class Main {
public static void main(String[] args) {
String s3 = "Hello";
String s4 = new String(s3);
if (s3.equals(s4)) {
System.out.println("The strings are equal");
} else {
System.out.println("The strings are not equal");
}
}
}
この例では、s1とs2オブジェクトの値が同じなので、equals()メソッドはtrueを返し、"The strings are equal"と出力されます。文字列の比較については文字列の比較で詳しく説明しています。
制御フロー構文では、短絡評価についても気をつけておく必要があります。短絡評価とは、論理演算子&&および||が用いられる述語内で、最初のオペランドの値に基づいて式の結果が決定できる場合、残りの評価をスキップする手法です。
例えば、x && yという式では、xが偽の場合、yの値に関係なく式の結果は偽であるため、yを評価する必要はありません。同様に、x || yという式では、xが真の場合、yの値に関係なく式の結果は真であるため、yを評価する必要はありません。
public class Main {
public static void main(String[] args) {
int x = 5;
int y = 10;
// xは負ではないので、第2オペランドy > 0は評価されず、elseブロックが実行されます
// false && trueもfalse && falseもfalseと評価されるので、第2オペランドの値は関係ない
if (x < 0 && y > 0) {
System.out.println("x is negative and y is positive");
} else {
System.out.println("x is not negative or y is not positive");
}
}
}
短絡評価については、CS基礎/初級/関数で詳しく学習できます。
条件付き三項演算子とは、3つのオペランドをとる条件演算子です。条件付き三項演算子は、if-else文を記述するための省略記法です。基本的な構文は次のとおりです。
predicate ? valueOfTrue : valueOfFalse
例えば、次のようなif-else文があります。
int x = 5;
int y;
if (x > 0) {
y = 10;
} else {
y = 20;
}
条件付き三項演算子を用いて次のように書き換えることができます。
int x = 5;
int y = x > 0 ? 10 : 20;
条件付き三項演算子は、まず条件式「x > 0」を評価します。それが真であれば、yに10が代入され、偽の場合、yに20が代入されます。
短絡評価については、CS基礎/中級/制御フローで詳しく学習できます。