Avoid Jump Statements in Finally Blocks
What is it?
This practice is focused on avoiding the use of jump statements, such as return
, break
, continue
, and throw
, within finally
blocks in Java. These statements can suppress exceptions that are thrown within the try
or catch
blocks, leading to unexpected program behavior and making debugging difficult.
Why apply it?
Using jump statements in finally
blocks can cause the program to ignore exceptions and terminate abnormally, making code execution unpredictable and maintenance challenging.
How to fix it?
Do not use jump statements within finally
blocks. Instead, allow the finally
block to complete its execution naturally to ensure exceptions are properly propagated.
Examples
Example 1:
Negative
This negative example uses a return
statement within the finally
block, which prevents the propagation of the exception thrown in the try
block.
public class Main {
public static void main(String[] args) {
try {
someMethod();
System.out.println("Incorrect execution");
} catch (RuntimeException e) {
System.out.println("This should print but doesn't");
}
}
public static void someMethod() {
try {
throw new RuntimeException("Exception thrown");
} finally {
System.out.println("Finally block executed");
return; /* Noncompliant */
}
}
}
Example 2:
Positive
This positive example avoids using the return
statement within the finally
block, allowing the program to correctly propagate any exceptions that occur in the try
block.
public class Main {
public static void main(String[] args) {
try {
someMethod();
System.out.println("This should not print");
} catch (RuntimeException e) {
System.out.println("Caught an exception: " + e.getMessage());
}
}
public static void someMethod() {
try {
throw new RuntimeException("Exception thrown");
} finally {
System.out.println("Finally block executed");
}
}
}
Negative
This negative example contains a continue
statement within the finally
block of a loop, which disrupts exception handling.
public class ExampleNegative {
public static void main(String[] args) throws Exception {
try {
yetAnotherMethod();
} catch (Exception e) {
System.out.println("This will not be printed");
}
}
public static void yetAnotherMethod() throws Exception {
for (int i = 0; i < 5; i++) {
try {
if (i == 2) {
throw new Exception("Loop exception");
}
System.out.println("Inside loop: " + i);
} finally {
System.out.println("Finally block, i = " + i);
if (i == 3) {
break; /* Noncompliant */
}
}
}
}
}
Example 3:
Positive
In this positive example, the finally
block is used solely for cleanup purposes, avoiding any suppression of exceptions thrown in the try
block.
public class ExamplePositive {
public static void main(String[] args) {
try {
anotherMethod();
} catch (Exception e) {
System.out.println("Exception caught: " + e.getMessage());
}
}
public static void anotherMethod() throws Exception {
try {
throw new Exception("Test exception");
} finally {
System.out.println("Cleanup in finally block");
}
}
}