1. 式 vs 文
Java の構成要素は大きく 2 つに分かれます。文(Statement)と 式(Expression)です。文は「実行される」もの、式は「評価される」ものとよく説明されますが、ここではそれが本質ではありません。
文と式の本質的な違いは、式には評価結果があることです。結果には第一に型があり、第二にその結果をどこかに代入したり、別の式の一部として利用できます。
例:
| コード | 注記 |
|---|---|
|
文 |
|
式、型は boolean |
|
式。型は変数 i の型に一致 |
|
式。型は変数 x の型に一致 |
では、これで何が得られるのでしょうか?
第一に、多くの「文」は実は評価結果を持つ式でもあるという事実を利用できます。例えば、次のコードは動作します。
int x, y, z;
x = y = z = 1; // x = (y = (z = 1));
第二に、必要なら式の評価結果を無視できます。
console.nextLine(); // 入力の結果は無視する
式が結果以外にも有用な副作用を持ち、その動作が重要で結果自体は重要でない場合など、評価結果を無視することがあります。
2. 三項演算子
この小ワザは先ほどよりも興味深いものです。Java には特別な三項(トリナリ)演算子があります。これは演算子 if–else の省略記法に似ています。
Condition ? Expression1 : Expression2;
条件が真なら Expression1 が評価され、そうでなければ Expression2 が評価されます。条件の後に疑問符が続き、2 つの式はコロンで区切られます。
三項演算子は「式」なので、その評価結果を何かに代入できる点が、演算子 if-else と大きく異なります。
例えば 2 つの数の最小値を求めたいとします。三項演算子を使うと次のように書けます。
int a = 2;
int b = 3;
int min = a < b ? a : b;
あるいは、ある条件に応じて変数に異なる値を代入したいとします。どう書けばよいでしょうか?
方法1 — 演算子 if-else を使う:
int age = 25;
int money;
if (age > 30)
money = 100;
else
money = 50;
方法2 — 三項演算子、つまり演算子 if-else の短縮記法を使う:
int age = 25;
int money = age > 30 ? 100 : 50;
どちらを使うべきか?実行速度の観点ではほぼ差はありません。ここで重要なのは読みやすさです。コードは正しく動くだけでなく、他のプログラマが読みやすいことも大切です。
簡単な目安は次のとおりです。コードが 1 行に収まるなら三項演算子、1 行に収まらないなら if-else を使いましょう。
3. 動作のニュアンス
値の型
重要: 三項演算子の両方の分岐(<value_if_true> と <value_if_false>)は同じ型であるか、互換性が必要です(例えば両方 String、または両方 int など)。
動く例:
int a = 10, b = 20;
int max = (a > b) ? a : b; // 両方の分岐は int
コンパイルエラー:
int a = 10, b = 20;
// String と int は非互換
String result = (a > b) ? "大きい" : 0; // コンパイルエラー: int を String 型の変数に代入できない
正しい例:
int a = 10, b = 20;
String result = (a > b) ? "大きい" : "以下";
例: 数値の扱い
三項演算子で絶対値を求めてみましょう。
int number = -5;
int abs = (number >= 0) ? number : -number;
System.out.println(abs); // 5
4. 三項演算子をアプリケーションへ組み込む
簡単な対話型アプリを書いてみましょう。挨拶に加えて、来年何歳になるかを伝え、成人かどうかを表示します。
System.out.print("あなたの名前を入力してください: ");
String name = console.nextLine();
System.out.print("あなたの年齢を入力してください: ");
int age = console.nextInt();
int nextYear = age + 1;
String status = (nextYear >= 18) ? "成人" : "未成年";
System.out.println("こんにちは、" + name + "さん!来年は " + nextYear + " 歳になります。あなたは " + status + " です。");
詳細の説明:
変数 status は三項演算子で計算しています。1 年後の年齢が 18 以上なら成人(すでに成人ならそのまま)です。
5. 入れ子の三項演算子に注意!
三項演算子は入れ子にできます(各分岐にさらに三項演算子を書けます)。しかし… 多くの場合読みづらく、後でコードを読む人(たとえ 2 日後の自分でも)が頭を抱えることになります。
例: 年齢によるカテゴリ判定
String category = (age < 7) ? "未就学児" :
(age < 18) ? "学生" :
(age < 65) ? "成人" : "高齢者";
意思決定表:
| 年齢 | 条件 | 結果 |
|---|---|---|
| < 7 | |
未就学児 |
| 7–17 | |
学生 |
| 18–64 | |
成人 |
| 65 以上 | それ以外 | 高齢者 |
この程度ならまだ読めますが、ロジックがさらに複雑なら if-else if-else を使ったほうがよいでしょう。
6. 小ワザ: 三項演算子と型 boolean
ときどき次のように書きたくなることがあります。
boolean adult = (age >= 18) ? true : false;
しかしこれは冗長です。(age >= 18) 自体が boolean を返します。だから次のように短くできます。
boolean adult = (age >= 18);
GO TO FULL VERSION