2 · Model and validate · 25 MIN
Parsing and exception boundaries
Catch a failure where you can make a meaningful decision.
Integer.parseInt reports malformed or out-of-range integers with NumberFormatException. The caller catches that specific exception and produces a predictable user-facing result. Catching Exception everywhere would also hide unrelated defects. Domain failures such as a negative quantity should have a distinct validation step after parsing. Resources such as readers need try-with-resources so they close on both successful and exceptional paths; a catch block alone does not establish resource ownership.
Catch the specific parse exception at the input boundary.
Read the example
public class Main {
static String describe(String text) {
try {
int n = Integer.parseInt(text);
return n < 0 ? "negative" : "quantity=" + n;
} catch (NumberFormatException error) { return "invalid integer"; }
}
public static void main(String[] args) {
for (String value : new String[]{"3","-1","oops"}) System.out.println(describe(value));
}
}Check the expected output
quantity=3 negative invalid integer
Your challenge
Add a maximum quantity of 1000 and a test for an integer too large to fit in int.
Solution cost: O(m) parsing for m characters. time · Account for collection storage separately from the returned result. space
Common trap
Catching Throwable can swallow serious VM errors along with ordinary failures.
Study the project implementation
public class Main {
static String describe(String text) {
try {
int n = Integer.parseInt(text);
return n < 0 ? "negative" : "quantity=" + n;
} catch (NumberFormatException error) { return "invalid integer"; }
}
public static void main(String[] args) {
for (String value : new String[]{"3","-1","oops"}) System.out.println(describe(value));
}
}Further reading: Official documentation
Next lesson: Streams and grouping without mutation →