Java Flow Controlインタビューの質問(回答)
1. 前書き
制御フローステートメントを使用すると、開発者は意思決定、ループ、および分岐を使用して、特定のコードブロックの実行フローを条件付きで変更できます。
この記事では、面接中にポップアップする可能性のあるフロー制御面接の質問と、必要に応じて、いくつかの質問について説明します。回答をよりよく理解するために例を実装します。
2. 質問
Q1. if-thenおよびif-then-elseステートメントについて説明します。 条件として使用できる式の種類は何ですか?
両方のステートメントは、特定の条件がtrueと評価された場合にのみ、プログラム内でコードを実行するようにプログラムに指示します。 ただし、if-then-elseステートメントは、if句がfalseと評価された場合に備えて、実行の2次パスを提供します。
if (age >= 21) {
// ...
} else {
// ...
}
他のプログラミング言語とは異なり、Javaは条件としてboolean式のみをサポートします。 別のタイプの式を使用しようとすると、コンパイルエラーが発生します。
Q2. switchステートメントを説明します。 switch句で使用できるオブジェクトタイプは何ですか?
スイッチを使用すると、変数の値に基づいて複数の実行パスを選択できます。
各パスにはcaseまたはdefaultのラベルが付けられ、switchステートメントは各case式の一致を評価し、breakまで一致ラベルに続くすべてのステートメントを実行します。 sステートメントが見つかりました。 一致するものが見つからない場合は、代わりにdefaultブロックが実行されます。
switch (yearsOfJavaExperience) {
case 0:
System.out.println("Student");
break;
case 1:
System.out.println("Junior");
break;
case 2:
System.out.println("Middle");
break;
default:
System.out.println("Senior");
}
byte、short、char、int、それらのラップされたバージョン、enums、およびStringsをswitch値として使用できます。
Q3. switchのcase句にbreakステートメントを入れるのを忘れるとどうなりますか?
switchステートメントは失敗します。 これは、breakステートメントが見つかるまで、それらのラベルが式の値と一致しなくても、すべてのcaseラベルの実行を継続することを意味します。
これを示す例を次に示します。
int operation = 2;
int number = 10;
switch (operation) {
case 1:
number = number + 10;
break;
case 2:
number = number - 4;
case 3:
number = number / 3;
case 4:
number = number * 10;
break;
}
コードを実行した後、numberは6ではなく20の値を保持します。 これは、同じアクションを複数のケースに関連付ける場合に役立ちます。
Q4. if-then-elseステートメントよりもswitchを使用する方が望ましいのはいつですか?
switchステートメントは、単一の変数を多数の単一の値に対してテストする場合、または複数の値が同じコードを実行する場合に適しています。
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
days = 31;
break;
case 2:
days = 28;
break;
default:
days = 30;
}
値の範囲または複数の条件をチェックする必要がある場合は、if-then-elseステートメントをお勧めします。
if (aPassword == null || aPassword.isEmpty()) {
// empty password
} else if (aPassword.length() < 8 || aPassword.equals("12345678")) {
// weak password
} else {
// good password
}
Q5. Javaはどのタイプのループをサポートしていますか?
Javaは、for、while、およびdo-whileの3種類のループを提供します。
forループは、値の範囲を反復処理する方法を提供します。 タスクが何回繰り返されるかを事前に知っていると、最も役立ちます。
for (int i = 0; i < 10; i++) {
// ...
}
whileループは、特定の条件がtrueであるときに、ステートメントのブロックを実行できます。
while (iterator.hasNext()) {
// ...
}
do-whileは、whileステートメントのバリエーションであり、boolean式の評価はループの最下部にあります。 これにより、コードが少なくとも1回実行されることが保証されます。
do {
// ...
} while (choice != -1);
Q6. enhanced forループとは何ですか?
コレクション、配列、列挙型、またはIterableインターフェイスを実装するオブジェクトのすべての要素を反復処理するように設計されたforステートメントの別の構文です。
for (String aString : arrayOfStrings) {
// ...
}
Q7. どうすればループから予期して終了できますか?
breakステートメントを使用すると、ループの実行をすぐに終了できます。
for (int i = 0; ; i++) {
if (i > 10) {
break;
}
}
Q8. ラベルなしとラベル付きのbreakステートメントの違いは何ですか?
ラベルのないbreakステートメントは、最も内側のswitch、for、while、またはdo-whileステートメントを終了しますが、ラベルの付いたbreakは、外部の実行を終了します。ステートメント。
これを示す例を作成しましょう。
int[][] table = { { 1, 2, 3 }, { 25, 37, 49 }, { 55, 68, 93 } };
boolean found = false;
int loopCycles = 0;
outer: for (int[] rows : table) {
for (int row : rows) {
loopCycles++;
if (row == 37) {
found = true;
break outer;
}
}
}
番号37が見つかると、ラベル付きのbreakステートメントは最も外側のforループを終了し、それ以上のサイクルは実行されません。 したがって、loopCyclesは値5で終了します。
ただし、ラベルのないbreakは最も内側のステートメントを終了するだけで、制御フローを最も外側のforに戻し、table変数の次のrowにループを続けます。 loopCyclesは値8で終わります。
Q9. ラベルなしとラベル付きのcontinueステートメントの違いは何ですか?
ラベルのないcontinueステートメントは、最も内側のfor、while、またはdo-whileループの現在の反復の最後にスキップしますが、ラベルの付いたcontinueは指定されたラベルでマークされた外側のループ。
これを示す例を次に示します。
int[][] table = { { 1, 15, 3 }, { 25, 15, 49 }, { 15, 68, 93 } };
int loopCycles = 0;
outer: for (int[] rows : table) {
for (int row : rows) {
loopCycles++;
if (row == 15) {
continue outer;
}
}
}
推論は前の質問と同じです。 ラベル付けされたcontinueステートメントは、最も外側のforループを終了します。
したがって、loopCyclesは値5の保持を終了しますが、ラベルのないバージョンは最も内側のステートメントのみを終了し、loopCyclesを値9で終了します。
Q10. try-catch-finallyコンストラクト内の実行フローを記述します。
プログラムがtryブロックに入り、その内部で例外がスローされると、tryブロックの実行が中断され、制御の流れはcatchブロックで続行されます。スローされる例外を処理します。
そのようなブロックが存在しない場合、現在のメソッドの実行は停止し、呼び出しスタック上の前のメソッドに例外がスローされます。 または、例外が発生しない場合、すべてのcatchブロックが無視され、プログラムの実行は正常に続行されます。
tryブロックの本体内で例外がスローされたかどうかに関係なく、finallyブロックは常に実行されます。
Q11. finallyブロックが実行されない可能性があるのはどのような状況ですか?
tryまたはcatchブロックの実行中にJVMが終了した場合、たとえばSystem.exit(),を呼び出す場合、または実行中のスレッドが中断または強制終了された場合、finallyブロックは実行されません。
Q12. 次のコードを実行した結果はどうなりますか?
public static int assignment() {
int number = 1;
try {
number = 3;
if (true) {
throw new Exception("Test Exception");
}
number = 2;
} catch (Exception ex) {
return number;
} finally {
number = 4;
}
return number;
}
System.out.println(assignment());
コードは数値3を出力します。 finallyブロックは常に実行されますが、これはtryブロックが終了した後にのみ発生します。
この例では、try-catchブロックが終了する前にreturnステートメントが実行されます。 したがって、変数はすでにtestAssignmentメソッドの呼び出しコードに戻されているため、finallyブロック内のnumberへの割り当ては効果がありません。
Q13. 例外がスローされない場合でも、try-finallyブロックが使用される可能性があるのはどのような状況ですか?
このブロックは、break、continue、またはreturnステートメントを検出して、コードで使用されているリソースのクリーンアップを誤ってバイパスしないようにする場合に役立ちます。
HeavyProcess heavyProcess = new HeavyProcess();
try {
// ...
return heavyProcess.heavyTask();
} finally {
heavyProcess.doCleanUp();
}
また、スローされた例外をローカルで処理できない場合や、リソースを解放しながら現在のメソッドで例外をスローしたい場合があります。
public void doDangerousTask(Task task) throws ComplicatedException {
try {
// ...
task.gatherResources();
if (task.isComplicated()) {
throw new ComplicatedException("Too difficult");
}
// ...
} finally {
task.freeResources();
}
}
Q14. try-with-resourcesはどのように機能しますか?
try-with-resourcesステートメントは、tryブロックを実行する前に、1つ以上のリソースを宣言して初期化し、ブロックが正常に完了したか突然完了したかに関係なく、ステートメントの最後でリソースを自動的に閉じます。 AutoCloseableまたはCloseableインターフェースを実装する任意のオブジェクトをリソースとして使用できます。
try (StringWriter writer = new StringWriter()) {
writer.write("Hello world!");
}
3. 結論
この記事では、制御フローステートメントに関するJava開発者向けの技術面接で最も頻繁に寄せられる質問のいくつかを取り上げました。 これは、さらなる調査の開始としてのみ扱われるべきであり、網羅的なリストとして扱われるべきではありません。
インタビューで頑張ってください。