Checked Exceptions in Lambdas
Why a lambda cannot throw a checked exception, and the three honest ways around it.
Open this lesson in the learning hubKey points
Function,Predicateand the rest declare no checked exceptions, so a lambda body cannot throw one.- Option 1: catch inside the lambda and return a fallback. Simple, but the failure quietly disappears.
- Option 2: wrap it in an unchecked exception. The stream stops on the first bad element, which is often right.
- Option 3: return a small result record, then
partitioningBythe successes from the failures. - A sneaky-throw helper compiles, but callers get an exception no signature ever mentioned. Avoid it.
- Decide up front whether one bad element should stop the batch or just be reported at the end.
Example
import java.util.*;
import java.util.stream.*;
public class Main {
// Pretend this reads a file or calls a service: it declares a checked exception.
static int parse(String s) throws Exception {
for (char c : s.toCharArray()) {
if (c < '0' || c > '9') {
throw new Exception("not a number: " + s);
}
}
return Integer.parseInt(s);
}
record Result(String input, Integer value, String error) {
boolean ok() {
return error == null;
}
}
public static void main(String[] args) {
List<String> raw = List.of("10", "oops", "32");
// 1. Swallow it and fall back. Cheap, but the failure disappears.
System.out.println("fallback : " + raw.stream().map(s -> {
try {
return parse(s);
} catch (Exception e) {
return -1;
}
}).toList());
// 2. Rethrow unchecked. The whole stream stops on the first bad element.
try {
raw.stream().mapToInt(s -> {
try {
return parse(s);
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}).sum();
} catch (IllegalStateException e) {
System.out.println("rethrown : " + e.getMessage());
}
// 3. Carry the outcome as data, then split successes from failures.
Map<Boolean, List<Result>> split = raw.stream().map(s -> {
try {
return new Result(s, parse(s), null);
} catch (Exception e) {
return new Result(s, null, e.getMessage());
}
}).collect(Collectors.partitioningBy(Result::ok));
System.out.println("ok : " + split.get(true).stream().map(Result::value).toList());
System.out.println("failed : " + split.get(false).stream().map(Result::error).toList());
}
}
If the failure must not stop the batch, turn it into data and collect it.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Streams course, and every lesson in it is listed on the Streams contents page.