Java Flow Control Interview Questions (+ Answers) – Java流控制面试问题(+答案)

最后修改: 2017年 4月 15日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

Control flow statements allow developers to use decision making, looping and branching to conditionally change the flow of execution of particular blocks of code.

控制流语句允许开发人员使用决策、循环和分支来有条件地改变特定代码块的执行流程。

In this article, we’ll go through some flow control interview questions that might pop up during an interview and, where appropriate; we’ll implement examples to understand their answers better.

在这篇文章中,我们将通过一些在面试中可能出现的流程控制面试问题,并在适当的地方;我们将实施例子来更好地理解他们的答案。

2. Questions

2.问题

Q1. Describe the if-then and if-then-else Statements. What Types of Expressions Can Be Used as Conditions?

问题1.描述一下if-thenif-then-else语句 哪些类型的表达式可以作为条件使用?

Both statements tell our program to execute the code inside of them only if a particular condition evaluates to true. However, the if-then-else statement provides a secondary path of execution in case the if clause evaluates to false:

这两个语句都告诉我们的程序,只有在某个特定条件评估为时,才执行其中的代码。然而,if-then-else语句在if子句评估为false的情况下提供了第二条执行路径。

if (age >= 21) {
    // ...
} else {
    // ...
}

Unlike other programming languages, Java only supports boolean expressions as conditions. If we try to use a different type of expression, we’ll get a compilation error.

与其他编程语言不同,Java只支持boolean表达式作为条件。如果我们试图使用不同类型的表达式,我们会得到一个编译错误。

Q2. Describe the switch Statement. What Object Types Can Be Used in the switch Clause?

问题2 描述一下switch语句 哪些对象类型可用于switch语句中?

Switch allows the selection of several execution paths based on a variables’ value.

切换允许根据一个变量的值来选择几个执行路径。

Each path is labeled with case or default, the switch statement evaluates each case expression for a match and executes all statements that follow the matching label until a break statement is found. If it can’t find a match, the default block will be executed instead:

每个路径都标有casedefaultswitch语句评估每个case表达式是否匹配,并执行匹配标签后的所有语句,直到找到break语句。如果找不到匹配的语句,将执行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");
}

We can use byte, short, char, int, their wrapped versions, enums and Strings as switch values.

我们可以使用byteshortcharint、它们的包装版本、enums和Strings作为开关值。

Q3. What Happens When We Forget to Put a break Statement in a case Clause of a switch?

Q3.当我们忘记在switchcase子句中放入break语句时会发生什么?

The switch statement falls-trough. This means that it will continue the execution of all case labels until if finds a break statement, even though those labels don’t match the expression’s value.

switch 语句是落空的。这意味着它将继续执行所有case标签,直到找到break语句,即使这些标签与表达式的值不匹配。

Here’s an example to demonstrate this:

这里有一个例子来证明这一点。

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;
}

After running the code, number holds the value 20, instead of 6. This can be useful in situations when we want to associate the same action with multiple cases.

运行代码后,number保持的值是20,而不是6。这在我们想把同一个动作与多个案例联系起来的情况下很有用。

Q4. When Is It Preferable to Use a Switch Over an If-Then-Else Statement and Vice Versa?

Q4.什么时候使用Switch而不是If-then-Else语句,反之亦然?

A switch statement is better suited when testing a single variable against many single values or when several values will execute the same code:

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;
}

An if-then-else statement is preferable when we need to check ranges of values or multiple conditions:

当我们需要检查值的范围或多个条件时,if-then-else语句是比较好的。

if (aPassword == null || aPassword.isEmpty()) {
    // empty password
} else if (aPassword.length() < 8 || aPassword.equals("12345678")) {
    // weak password
} else {
    // good password
}

Q5. What Types of Loops Does Java Support?

Q5.Java支持哪些类型的循环?

Java offers three different types of loops: for, while, and do-while.

Java提供三种不同类型的循环。for, while, 和do-while

A for loop provides a way to iterate over a range of values. It’s most useful when we know in advance how many times a task is going to be repeated:

for 循环提供了一种在一个数值范围内进行迭代的方法。当我们事先知道一个任务要重复多少次时,它是最有用的。

for (int i = 0; i < 10; i++) {
     // ...
}

A while loop can execute a block of statements while a particular condition is true:

一个while循环可以在一个特定条件为时执行一个语句块。

while (iterator.hasNext()) {
    // ...
}

A do-while is a variation of a while statement in which the evaluation of the boolean expression is at the bottom of the loop. This guarantees that the code will execute at least once:

do-whilewhile语句的一种变体,其中boolean表达式的评估位于循环的底部。这可以保证代码至少执行一次。

do {
    // ...
} while (choice != -1);

Q6. What Is an enhanced for Loop?

Q6.什么是增强的环路?

Is another syntax of the for statement designed to iterate through all the elements of a collection, array, enum or any object implementing the Iterable interface:

for语句的另一种语法,旨在遍历一个集合、数组、枚举或任何实现Iterable接口的对象中的所有元素。

for (String aString : arrayOfStrings) {
    // ...
}

Q7. How Can You Exit Anticipatedly From a Loop?

Q7.你如何从一个循环中预期地退出?

Using the break statement, we can terminate the execution of a loop immediately:

使用break语句,我们可以立即终止一个循环的执行。

for (int i = 0; ; i++) {
    if (i > 10) {
        break;
    }
}

Q8. What Is the Difference Between an Unlabeled and a Labeled break Statement?

Q8.无标签和有标签的break声明之间的区别是什么?

An unlabeled break statement terminates the innermost switch, for, while or do-while statement, whereas a labeled break ends the execution of an outer statement.

一个未标记的break语句终止最内层的switchforwhiledo-while语句,而一个标记的break则结束外层语句的执行。

Let’s create an example to demonstrate this:

让我们创造一个例子来证明这一点。

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;
        }
    }
}

When the number 37 is found, the labeled break statement terminates the outermost for loop, and no more cycles are executed. Thus, loopCycles ends with the value of 5.

当找到数字37时,标记的break语句终止了最外层的for循环,并且不再执行任何循环。因此,loopCycles以5的值结束。

However, the unlabeled break only ends the innermost statement, returning the flow of control to the outermost for that continues the loop to the next row in the table variable, making the loopCycles end with a value of 8.

然而,没有标记的break只结束了最里面的语句,将控制流返回到最外面的for,继续循环到table变量中的下一个row,使得loopCycles的值为8。

Q9. What Is the Difference Between an Unlabeled and a Labeled continue Statement?

Q9.无标签和有标签的继续声明之间的区别是什么?

An unlabeled continue statement skips to the end of the current iteration in the innermost for, while, or do-while loop, whereas a labeled continue skips to an outer loop marked with the given label.

一个没有标记的continue语句会跳到最里面的forwhiledo-while循环中的当前迭代结束,而一个有标记的continue会跳到一个标有给定标记的外循环。

Here’s an example that demonstrates this:

这里有一个例子可以证明这一点。

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;
        }
    }
}

The reasoning is the same as in the previous question. The labeled continue statement terminates the outermost for loop.

推理与前一个问题相同。标记的continue语句终止了最外层的for循环。

Thus, loopCycles ends holding the value 5, whereas the unlabeled version only terminates the innermost statement, making the loopCycles end with a value of 9.

因此,loopCycles以5的值结束,而未标记的版本只终止最里面的语句,使loopCycles以9的值结束。

Q10. Describe the Execution Flow Inside a try-catch-finally Construct.

问题10 描述try-catch-finally结构内部的执行流程

When a program has entered the try block, and an exception is thrown inside it, the execution of the try block is interrupted, and the flow of control continues with a catch block that can handle the exception being thrown.

当程序进入try块时,如果在该块内抛出一个异常,try块的执行就会被中断,控制流将继续由catch块处理被抛出的异常。

If no such block exists then the current method execution stops, and the exception is thrown to the previous method on the call stack. Alternatively, if no exception occurs, all catch blocks are ignored, and program execution continues normally.

如果不存在这样的块,那么当前方法的执行就会停止,并将异常抛给调用栈中的前一个方法。或者,如果没有异常发生,那么所有的catch块都会被忽略,程序继续正常执行。

A finally block is always executed whether an exception was thrown or not inside the body of the try block.

无论finally块内部是否抛出了异常,try块都会被执行。

Q11. In Which Situations the finally Block May Not Be Executed?

Q11.在哪些情况下,最终块可能不会被执行?

When the JVM is terminated while executing the try or catch blocks, for instance, by calling System.exit(), or when the executing thread is interrupted or killed, then the finally block is not executed.

当JVM在执行trycatch块时被终止,例如,调用System.exit(),或执行线程被中断或杀死时,那么finally块不会被执行。

Q12. What Is the Result of Executing the Following Code?

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());

The code outputs the number 3. Even though the finally block is always executed, this happens only after the try block exits.

该代码输出数字3。尽管finally块总是被执行,但这只发生在try块退出之后。

In the example, the return statement is executed before the try-catch block ends. Thus, the assignment to number in the finally block makes no effect, since the variable is already returned to the calling code of the assignment method.

在这个例子中,return语句在try-catch块结束前被执行。因此,在finally块中对number的赋值没有任何影响,因为该变量已经被返回到assignment方法的调用代码中。

Q13. In Which Situations try-finally Block Might Be Used Even When Exceptions Might Not Be Thrown?

Q13.在哪些情况下try-finally块可以被使用,即使在异常可能不被抛出的情况下?

This block is useful when we want to ensure we don’t accidentally bypass the clean up of resources used in the code by encountering a break, continue or return statement:

当我们想确保不会因为遇到breakcontinuereturn语句而意外地绕过对代码中使用的资源的清理时,这个块就很有用。

HeavyProcess heavyProcess = new HeavyProcess();
try {
    // ...
    return heavyProcess.heavyTask();
} finally {
    heavyProcess.doCleanUp();
}

Also, we may face situations in which we can’t locally handle the exception being thrown, or we want the current method to throw the exception still while allowing us to free up resources:

另外,我们可能会面临这样的情况:我们无法在本地处理被抛出的异常,或者我们希望当前方法仍然抛出异常,同时允许我们释放资源。

public void doDangerousTask(Task task) throws ComplicatedException {
    try {
        // ...
        task.gatherResources();
        if (task.isComplicated()) {
            throw new ComplicatedException("Too difficult");
        }
        // ...
    } finally {
        task.freeResources();
    }
}

Q14. How Does try-with-resources Work?

Q14.有资源的尝试 “是如何运作的?

The try-with-resources statement declares and initializes one or more resources before executing the try block and closes them automatically at the end of the statement regardless of whether the block completed normally or abruptly. Any object implementing AutoCloseable or Closeable interfaces can be used as a resource:

try-with-resources语句在执行try块之前声明并初始化一个或多个资源,并在语句结束时自动关闭这些资源,无论该块是正常完成还是突然结束。任何实现AutoCloseableCloseable接口的对象都可以作为资源使用。

try (StringWriter writer = new StringWriter()) {
    writer.write("Hello world!");
}

3. Conclusion

3.结论

In this article, we covered some of the most frequently asked questions appearing in technical interviews for Java developers, regarding control flow statements. This should only be treated as the start of further research and not as an exhaustive list.

在这篇文章中,我们介绍了一些在Java开发者技术面试中最常出现的关于控制流语句的问题。这只应被视为进一步研究的开始,而不是一个详尽的清单。

Good luck in your interview.

祝你在面试中好运。

Next »

Java Exceptions Interview Questions (+ Answers)

« Previous

Java Generics Interview Questions (+Answers)