はじめに
Java Silver(SE 21対応)試験対策として、制御構文に関する問題を10問まとめました。switch文のフォールスルー、ラベル付きbreak、do-whileの挙動など、試験で狙われやすいポイントを中心に構成しています。
問1 ⭐ if-elseのネスト
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
int x = 5;
if (x > 3)
if (x > 10)
System.out.println("A");
else
System.out.println("B");
}
}
A. A
B. B
C. 何も出力されない
D. コンパイルエラー
解答と解説
正解: B
インデントに惑わされないでください。elseは**最も近いif**に結びつきます。
実際の構造は以下の通りです。
if (x > 3) {
if (x > 10) {
System.out.println("A");
} else {
System.out.println("B");
}
}
-
x > 3→5 > 3→true(内側のifに進む) -
x > 10→5 > 10→false(elseに進む) -
"B"が出力される
これは「ダングリングelse問題」として知られる引っかけパターンです。
問2 ⭐ switch文のフォールスルー
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
int day = 2;
switch (day) {
case 1:
System.out.print("Mon ");
case 2:
System.out.print("Tue ");
case 3:
System.out.print("Wed ");
break;
case 4:
System.out.print("Thu ");
}
}
}
A. Tue
B. Tue Wed
C. Tue Wed Thu
D. Mon Tue Wed
解答と解説
正解: B
case 2にマッチしますが、breakがないためフォールスルーが発生し、case 3の処理も実行されます。case 3の最後にbreakがあるため、そこでswitch文を抜けます。
出力はTue Wed です(末尾にスペースあり)。
フォールスルーはbreakを書き忘れたバグの原因になりやすく、試験でも頻出です。
問3 ⭐⭐ switch文で使える型
次のコードのうち、コンパイルエラーになるものはどれですか?
public class Main {
public static void main(String[] args) {
// (1)
long val1 = 1L;
switch (val1) {
case 1L: System.out.println("long"); break;
}
// (2)
String val2 = "A";
switch (val2) {
case "A": System.out.println("String"); break;
}
// (3)
int val3 = 1;
switch (val3) {
case 1: System.out.println("int"); break;
}
}
}
A. (1)のみ
B. (2)のみ
C. (1)と(2)
D. すべて正常にコンパイルできる
解答と解説
正解: A
switch式に使用できる型は以下に限られます。
-
byte,short,char,int(およびそのラッパー型) Stringenum
longは使用できません。 したがって(1)はコンパイルエラーです。
float、double、booleanもswitchでは使用できません。
問4 ⭐⭐ 拡張for文
次のコードの出力は何ですか?
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
for (String s : list) {
if (s.equals("B")) {
list.remove(s);
}
}
System.out.println(list);
}
}
A. [A, C]
B. [A, B, C]
C. ConcurrentModificationExceptionが発生
D. コンパイルエラー
解答と解説
正解: C
拡張for文(for-each)はイテレータを内部的に使用しています。ループ中にlist.remove()でコレクションを直接変更すると、イテレータの整合性が崩れ、ConcurrentModificationExceptionがスローされます。
安全に削除するにはIteratorのremove()メソッドを使います。
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (it.next().equals("B")) {
it.remove(); // イテレータ経由なら安全
}
}
またはremoveIfメソッドを使う方法もあります。
list.removeIf(s -> s.equals("B"));
問5 ⭐ do-while文
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
int i = 10;
do {
System.out.print(i + " ");
i++;
} while (i < 10);
}
}
A. 何も出力されない
B. 10
C. 10 11 12 ...(無限ループ)
D. コンパイルエラー
解答と解説
正解: B
do-while文は必ず1回はループ本体を実行してから条件を評価します。
- ループ本体を実行:
10を出力、iは11になる - 条件
i < 10→11 < 10→false→ ループ終了
while文と異なり、do-while文は条件が最初からfalseでも1回は実行されます。
問6 ⭐⭐ for文の変則的な書き方
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
for (int i = 0, j = 10; i < j; i++, j--) {
System.out.print(i + " ");
}
}
}
A. 0 1 2 3 4
B. 0 1 2 3 4 5
C. 0 1 2 3
D. 0 1 2 3 4 5 6 7 8 9
解答と解説
正解: A
各反復でのiとjの値を追跡します。
| 反復 | i | j | i < j | 出力 |
|---|---|---|---|---|
| 1 | 0 | 10 | true | 0 |
| 2 | 1 | 9 | true | 1 |
| 3 | 2 | 8 | true | 2 |
| 4 | 3 | 7 | true | 3 |
| 5 | 4 | 6 | true | 4 |
| 6 | 5 | 5 | false | - |
iとjが5で等しくなった時点でi < jがfalseになり、ループが終了します。
for文の初期化部では同じ型の複数変数をカンマで宣言でき、更新部でも複数の式をカンマで記述できます。
問7 ⭐⭐ continue文
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
if (i % 2 == 0) {
continue;
}
System.out.print(i + " ");
}
}
}
A. 0 2 4
B. 1 3
C. 0 1 2 3 4
D. 1 2 3 4
解答と解説
正解: B
continue文は、ループの残りの処理をスキップして次の反復に進みます。
-
i=0: 偶数 →continue→ スキップ -
i=1: 奇数 →1を出力 -
i=2: 偶数 →continue→ スキップ -
i=3: 奇数 →3を出力 -
i=4: 偶数 →continue→ スキップ
偶数のときにスキップされるため、奇数のみ出力されます。
問8 ⭐⭐⭐ ラベル付きbreak
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
outer:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == 1 && j == 1) {
break outer;
}
System.out.print(i + "" + j + " ");
}
}
}
}
A. 00 01 02 10
B. 00 01 02 10 12 20 21 22
C. 00 01 02 10 11
D. 00 01 02
解答と解説
正解: A
ラベル付きbreakは、指定したラベルのループ全体を抜けます。
-
i=0, j=0: 条件不成立 →00出力 -
i=0, j=1: 条件不成立 →01出力 -
i=0, j=2: 条件不成立 →02出力 -
i=1, j=0: 条件不成立 →10出力 -
i=1, j=1: 条件成立 →break outer→ 外側ループも含めて終了
ラベルなしのbreakでは内側ループしか抜けられません。ラベル付きbreakは外側ループを含めて脱出できます。
問9 ⭐⭐⭐ switch文のcaseにおける定数式
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
final int A = 1;
int B = 2;
int x = 1;
switch (x) {
case A:
System.out.println("A");
break;
case B:
System.out.println("B");
break;
}
}
}
A. A
B. B
C. コンパイルエラー
D. 実行時エラー
解答と解説
正解: C
caseラベルにはコンパイル時定数式が必要です。
-
Aはfinal int A = 1;で宣言されており、コンパイル時定数です。OK -
Bはfinalではないため、コンパイル時定数ではありません。コンパイルエラー
caseラベルに使用できるのは、リテラル、final変数(コンパイル時に値が確定するもの)、enum定数です。
final int B = 2; // finalを付ければOK
問10 ⭐⭐ while文の条件
次のコードの出力は何ですか?
public class Main {
public static void main(String[] args) {
int count = 0;
while (count < 3) {
count++;
if (count == 2) {
continue;
}
System.out.print(count + " ");
}
}
}
A. 1 2 3
B. 1 3
C. 0 1 3
D. 1
解答と解説
正解: B
各反復を追跡します。
| 反復 | count(++後) | count == 2 | 出力 |
|---|---|---|---|
| 1 | 1 | false | 1 |
| 2 | 2 | true(continue) | - |
| 3 | 3 | false | 3 |
| 4 | - | - | count < 3がfalseで終了 |
-
count=2のときcontinueでprintがスキップされるため、2は出力されません -
countのインクリメントはcontinueの前にあるため、無限ループにはなりません
continueの位置がインクリメントの前にある場合、カウンタが更新されず無限ループになることがあるので要注意です。
参考
- Oracle Java SE 21 Language Specification - Chapter 14. Blocks, Statements, and Patterns
- Oracle Java Tutorials - Control Flow Statements
@kotaro_ai_lab
AI活用や開発効率化について発信しています。フォローお気軽にどうぞ!