Definition
Three things to know about number parsing:
- Invalid input throws.
Integer.parseInt("abc")throwsNumberFormatException. Same for empty strings, null, overflow, and stray characters. - Radix overload.
Integer.parseInt("FF", 16)parses hexadecimal and returns 255.parseInt("1010", 2)parses binary and returns 10. - Reverse conversion.
Integer.toHexString(255)returns"ff".Integer.toBinaryString(10)returns"1010".
A bank teller reads an amount written on a slip. If it says "abc" where a number should be, the teller raises an error rather than guessing. Sometimes amounts arrive in hex code from a payment terminal: the teller uses a hex codebook to decode "FF" into 255. And when the bank needs to print a status flag in binary, it converts the number using the binary codebook.
Understanding the Concepts
What exactly throws NumberFormatException?
// All of these throw NumberFormatException:
Integer.parseInt("abc"); // not a number
Integer.parseInt(""); // empty string
Integer.parseInt(null); // null
Integer.parseInt("12.5"); // decimal point not valid for int
Integer.parseInt("1,000"); // comma not valid
Integer.parseInt(" 42 "); // whitespace not valid (trim first!)
Integer.parseInt("99999999999"); // exceeds Integer.MAX_VALUE
Integer.parseInt("42L"); // L suffix is for source code, not parsing
NumberFormatException is unchecked (extends IllegalArgumentException). The compiler does not force you to catch it, but any code parsing external input should.
How do you handle parse failures safely?
// BAD: crashes on invalid input
int count = Integer.parseInt(userInput);
// GOOD: catch and handle
public OptionalInt safeParse(String input) {
if (input == null || input.isBlank()) {
return OptionalInt.empty();
}
try {
return OptionalInt.of(Integer.parseInt(input.trim()));
} catch (NumberFormatException e) {
log.warning("Invalid number: '" + input + "'");
return OptionalInt.empty();
}
}
// Usage:
int count = safeParse(rawField).orElse(0);
In banking, never silently default. Log the bad input and route the record for investigation.
How do you parse hex, binary, and octal?
// Hexadecimal (base 16)
int hex = Integer.parseInt("FF", 16); // 255
int hex2 = Integer.parseInt("1A3F", 16); // 6719
// Binary (base 2)
int bin = Integer.parseInt("1010", 2); // 10
int bin2 = Integer.parseInt("11111111", 2); // 255
// Octal (base 8)
int oct = Integer.parseInt("777", 8); // 511
// Any base from 2 to 36
int base36 = Integer.parseInt("ZZ", 36); // 1295
// Invalid digit for the radix also throws
try {
Integer.parseInt("2", 2); // '2' is not a valid binary digit
} catch (NumberFormatException e) {
System.out.println("Invalid binary digit");
}
How do you convert a number back to hex, binary, or octal?
int value = 255;
System.out.println(Integer.toHexString(value)); // "ff"
System.out.println(Integer.toBinaryString(value)); // "11111111"
System.out.println(Integer.toOctalString(value)); // "377"
System.out.println(Integer.toString(value, 36)); // "73" (any base 2-36)
// For negative numbers, toHexString uses the unsigned bit pattern:
System.out.println(Integer.toHexString(-1)); // "ffffffff" (all bits set)
// But toString with radix includes the sign:
System.out.println(Integer.toString(-1, 16)); // "-1"
How do you parse Long, Double, and BigDecimal?
// Long: for large values like timestamps
long timestamp = Long.parseLong("1698765432000");
// Double: for scientific values (never for money)
double rate = Double.parseDouble("8.5");
// BigDecimal: for money (always from String constructor)
BigDecimal balance = new BigDecimal("1000000.50");
// WRONG: new BigDecimal(1000000.50) captures double imprecision
Each wrapper has its own parse method. They all throw NumberFormatException on invalid input.
What about leading zeros and signs?
Integer.parseInt("+42"); // 42 (leading + is valid)
Integer.parseInt("-42"); // -42 (leading - is valid)
Integer.parseInt("042"); // 42 (leading zeros are valid in base 10, NOT octal)
// Note: parseInt("042") is 42, not 34. It does NOT auto-detect octal.
// For octal, use parseInt("42", 8) explicitly.
What are common mistakes?
- Not trimming input.
parseInt(" 42 ")throws. Always.trim()first. - Silently defaulting on failure.
catch (NFE e) { return 0; }hides data quality problems. Log and route. - Assuming parseInt detects the base.
parseInt("0xFF")throws. Remove the prefix and useparseInt("FF", 16). - Parsing money into int or double. Always use
new BigDecimal("...")for money. - Ignoring overflow.
parseInt("3000000000")throws because 3 billion exceeds int range. UseLong.parseLong()orBigInteger.
What should a senior engineer know?
- Java has no tryParse. Unlike C# which returns false for invalid input, Java throws. You must write your own safe-parse method or use a library.
- Integer.decode() handles prefixes:
Integer.decode("0xFF")returns 255,Integer.decode("077")returns 63 (octal). But it returns Integer, not int. - Spring Boot @RequestParam automatically parses and returns 400 Bad Request on NumberFormatException. You can customize the error response with
@ExceptionHandler. - In batch pipelines, always parse inside a try-catch per record so one bad record does not abort the entire batch.
Visual Overview
Input string → parseInt(string, radix)
│
├─ valid number in radix → return int value
│
└─ invalid → NumberFormatException
├ "abc" not numeric
├ "" empty
├ null null
├ "1,000" comma not valid
├ " 42 " whitespace (trim first)
├ overflow > Integer.MAX_VALUE
└ bad digit "2" in base 2
Radix parsing:
parseInt("FF", 16) → 255 (hex)
parseInt("1010", 2) → 10 (binary)
parseInt("777", 8) → 511 (octal)
Reverse:
toHexString(255) → "ff"
toBinaryString(10) → "1010"
toString(255, 36) → "73"
Key Takeaway
When Integer.parseInt receives a string it cannot interpret as a valid integer, it throws NumberFormatException. This happens for non-numeric text, empty strings, null, values with whitespace or commas, and numbers that overflow the int range. The exception is unchecked, so the compiler does not force you to handle it, but any code parsing external input should catch it, log the bad value, and route the record for investigation.
To parse numbers in other bases, use the radix overload: parseInt("FF", 16) for hex, parseInt("1010", 2) for binary. The radix must be 2 to 36. An invalid digit for the chosen base also throws. To convert back, use toHexString(), toBinaryString(), or toString(value, radix).
In banking, never silently default on a parse failure. A silent catch { return 0; } hides data quality problems. Log the bad input and route it. And never parse money into int or double: always use new BigDecimal("...") from a String.
One sentence to remember: parseInt throws NumberFormatException on any invalid input, use the radix overload for hex and binary, and always handle the exception explicitly in production code.
---