Fix java.lang.NumberFormatException: For input string trong Java

beginner Java2026-03-21| Java 8+, mọi hệ điều hành (Windows / Linux / macOS), mọi framework dùng Integer.parseInt(), Long.parseLong(), Double.parseDouble()

Error Message

java.lang.NumberFormatException: For input string: "abc"
#java#numberformat#parsing#integer#string-conversion

TL;DRBạn đã gọi Integer.parseInt() — hoặc một hàm tương tự — trên một chuỗi không phải số hợp lệ. Chuỗi rỗng, một từ, giá trị như "1,000", hay thậm chí một khoảng trắng thừa đều sẽ gây ra lỗi này. Hãy bọc lời gọi trong try-catch, hoặc kiểm tra trước khi parse.

// Sửa nhanh — bọc bằng try-catch
try {
    int value = Integer.parseInt(input);
} catch (NumberFormatException e) {
    System.err.println("Invalid number: " + input);
    // xử lý giá trị mặc định, trả về lỗi, v.v.
}

Nguyên nhân gây ra lỗi nàyStack trace đầy đủ trông như sau:

Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
    at java.base/java.lang.Integer.parseInt(Integer.java:668)
    at java.base/java.lang.Integer.parseInt(Integer.java:786)
    at com.example.Main.main(Main.java:8)

Các phương thức parse của Java rất nghiêm ngặt. Chúng chỉ chấp nhận các ký tự chữ số, với dấu - hoặc + tùy chọn ở đầu. Chỉ vậy thôi. Bất kỳ thứ gì khác đều ném ra NumberFormatException. Những nguyên nhân phổ biến nhất:

  • Input từ người dùng chưa được kiểm tra ("abc", "", null)- Số có dấu phân cách hàng nghìn: "1,000"- Số có đơn vị đi kèm: "42px", "5MB"- Chuỗi số thực truyền vào parseInt: "3.14"- Chuỗi có khoảng trắng ở đầu hoặc cuối: " 7 "- Giá trị đọc từ CSV, JSON, hoặc cột cơ sở dữ liệu hóa ra là null hoặc bị lỗi định dạng## Các cách khắc phục### 1. Try-catch (phổ biến nhất)Đây là giải pháp cơ bản nhất. Dùng khi bạn cần phân biệt giá trị sai với giá trị thiếu — hoặc khi muốn ghi log cho thấy chính xác chuỗi nào gây ra vấn đề.
public static Integer safeParseInt(String s) {
    try {
        return Integer.parseInt(s);
    } catch (NumberFormatException e) {
        return null; // hoặc giá trị mặc định như 0
    }
}

// Sử dụng
Integer age = safeParseInt(request.getParameter("age"));
if (age == null) {
    throw new IllegalArgumentException("age must be a number");
}

2. Trim khoảng trắng trước khi parseKhoảng trắng thừa là một trong những nguyên nhân khó phát hiện nhất của lỗi này — đặc biệt với giá trị đọc từ file hoặc form. Một lần gọi .trim() thường giải quyết được vấn đề.

int value = Integer.parseInt(input.trim());

3. Kiểm tra bằng regex trướcLoại bỏ input sai ngay từ đầu. Cách này cho bạn thông báo lỗi rõ ràng, sớm thay vì một exception khó hiểu bị chôn vùi trong stack trace.

if (!input.matches("-?\\d+")) {
    throw new IllegalArgumentException("Expected an integer, got: " + input);
}
int value = Integer.parseInt(input);

4. Xử lý số được định dạng theo locale (1,000 / 1.000)parseInt không hiểu khái niệm locale — "1,234,567" sẽ luôn thất bại. Chuyển sang dùng NumberFormat khi đọc số được định dạng theo vùng miền cụ thể.

import java.text.NumberFormat;
import java.util.Locale;

String formatted = "1,234,567";
NumberFormat nf = NumberFormat.getInstance(Locale.US);
long value = nf.parse(formatted).longValue(); // 1234567

5. Parse số thực bị nhầm thành số nguyênCó "3.14" nhưng cần int thuần túy? Parse thành double trước, rồi ép kiểu. Bạn sẽ nhận được 3 — phần thập phân bị cắt bỏ, không phải làm tròn.

String s = "3.14";
int value = (int) Double.parseDouble(s); // 3

6. Apache Commons Lang (tiện ích tùy chọn)Đã dùng Commons Lang trong dự án? NumberUtils xử lý null, chuỗi rỗng, và input sai mà không ném exception — không cần boilerplate try-catch.

import org.apache.commons.lang3.math.NumberUtils;

int value = NumberUtils.toInt("abc", 0);   // trả về 0 (giá trị mặc định)
boolean valid = NumberUtils.isCreatable("123"); // true

7. Pattern Optional trong Java 8+Thích functional pipeline? Trả về OptionalInt thay vì ném exception hoặc trả về null. Cách này làm rõ ràng sự vắng mặt của giá trị — không có giá trị mặc định âm thầm ẩn trong code của bạn.

import java.util.OptionalInt;

public static OptionalInt tryParseInt(String s) {
    if (s == null || s.isBlank()) return OptionalInt.empty();
    try {
        return OptionalInt.of(Integer.parseInt(s.trim()));
    } catch (NumberFormatException e) {
        return OptionalInt.empty();
    }
}

// Sử dụng
tryParseInt(input).ifPresentOrElse(
    val -> System.out.println("Parsed: " + val),
    ()  -> System.out.println("Not a valid integer")
);

Các trường hợp đặc biệt cần chú ý- Input nullInteger.parseInt(null) ném NumberFormatException, không phải NPE. Ngạc nhiên, nhưng đúng như vậy. Luôn kiểm tra null trước khi gọi parse.- Tràn số nguyên"99999999999" vượt quá Integer.MAX_VALUE (2.147.483.647) và sẽ ném exception. Dùng Long.parseLong() hoặc new BigInteger(s) cho các giá trị lớn.- Chuỗi hex"0xFF" thất bại với parseInt thông thường. Dùng Integer.parseInt(s.substring(2), 16) hoặc cách gọn hơn là Integer.decode("0xFF").- Ký hiệu khoa học"1e5" không phải chuỗi số nguyên hợp lệ. Parse thành Double trước, rồi ép kiểu.## Kiểm tra sau khi sửaChạy các assertion này với tiện ích parse của bạn. Tất cả các trường hợp đặc biệt khó chịu đều được bao phủ — nếu mọi dòng đều pass, bạn đã sẵn sàng để triển khai.

// Input hợp lệ cơ bản
assert safeParseInt("42")   != null;
assert safeParseInt("-7")   != null;
assert safeParseInt(" 10 ") != null; // sau khi trim

// Nên trả về null / mặc định — không được ném exception
assert safeParseInt("")     == null;
assert safeParseInt("abc")  == null;
assert safeParseInt(null)   == null;
assert safeParseInt("3.14") == null;
assert safeParseInt("1,000") == null; // trừ khi bạn xóa dấu phẩy trước

System.out.println("All checks passed");

Không có exception, output hiển thị All checks passed? Cách sửa đã hoạt động đúng.

Tóm tắt nhanh- Dùng .trim() cho vấn đề khoảng trắng- Dùng try-catch cho input từ người dùng hoặc dữ liệu bên ngoài không đáng tin cậy- Dùng NumberFormat cho chuỗi được định dạng theo locale như "1,000"- Dùng Double.parseDouble() rồi ép kiểu cho chuỗi số thực- Dùng Long.parseLong() hoặc BigInteger cho giá trị vượt quá 2.147.483.647

Related Error Notes