Ошибка java.lang.NumberFormatException: For input string возникает в тот момент, когда метод Integer.parseInt(), Double.parseDouble() или другой метод парсинга получает строку, которую невозможно преобразовать в число. В сообщении исключения после двоеточия всегда указано конкретное проблемное значение — например, For input string: "12,5" или For input string: "abc". Именно этот фрагмент — главная подсказка для диагностики: он показывает, какие данные реально пришли в программу, а не те, которые разработчик ожидал увидеть.

Исключение относится к unchecked-исключениям (наследник IllegalArgumentException), поэтому компилятор не заставляет его обрабатывать, и проблема всплывает только во время выполнения. Чаще всего с ней сталкиваются при чтении пользовательского ввода, парсинге файлов, обработке параметров HTTP-запросов и десериализации JSON. Ниже разберём типовые причины, способы диагностики и надёжные приёмы защиты кода.

Что означает это исключение

Класс NumberFormatException сигнализирует: строка имеет неподходящий формат для преобразования в числовой тип. JVM выбрасывает его из методов семейства parseInt, parseLong, parseDouble, parseFloat, а также из конструкторов и методов valueOf() классов-обёрток Integer, Long, Double и других.

Стек-трейс указывает точную строку кода, где произошёл сбой. Типичный фрагмент выглядит так:

Exception in thread "main" java.lang.NumberFormatException: For input string: "25o"

at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)

at java.base/java.lang.Integer.parseInt(Integer.java:661)

at com.example.Main.main(Main.java:12)

Здесь видно, что проблема — символ «o» вместо нуля в строке "25o". Такие опечатки — частый источник ошибки при ручном вводе данных.

💡

Текст после «For input string:» — это реальное значение, вызвавшее сбой. Начинайте диагностику именно с него, а не с кода парсинга.

Основные причины возникновения

Чтобы исправить ошибку, нужно понять, почему строка оказалась «нечисловой». На практике причины сводятся к нескольким повторяющимся сценариям.

  • 🔤 Буквы и посторонние символы — строка содержит текст, опечатки или служебные символы: "12a", "1 000" с неразрывным пробелом.
  • 🌍 Локализованный формат чисел — десятичная запятая "12,5" вместо точки, разделители тысяч, специфичные для локали.
  • Пробелы и пустые строки — ведущие/концевые пробелы, табуляция, пустая строка "" или null.
  • 📏 Переполнение диапазона — число корректное, но не помещается в целевой тип, например "99999999999" для int.
  • 🔢 Несоответствие системы счисления — строка вида "0x1F" или восьмеричная запись при парсинге в десятичной системе.

Отдельного внимания заслуживает null: вызов Integer.parseInt(null) тоже бросает NumberFormatException, а не NullPointerException, что часто сбивает с толку при отладке. Это задокументированное поведение метода.

Как диагностировать источник проблемы

Первый шаг — найти в стек-трейсе свою строку кода (в примере выше это Main.java:12) и понять, откуда приходит проблемное значение. Если данные читаются извне — из файла, формы, API, аргументов командной строки — полезно залогировать сырое значение до парсинга.

String raw = request.getParameter("age");

System.out.println("RAW VALUE: [" + raw + "] length=" + (raw == null ? "null" : raw.length()));

int age = Integer.parseInt(raw);

Обратите внимание на вывод в квадратных скобках: так сразу видны невидимые символы — пробелы, табуляции, переносы строк. Особенно коварен неразрывный пробел (U+00A0), который часто приходит из Excel и веб-форм: визуально он неотличим от обычного, но метод trim() его не удаляет в старых версиях Java. Метод strip(), появившийся в Java 11, справляется с ним корректно.

📊 Где вы чаще всего встречаете NumberFormatException?
Парсинг пользовательского ввода
Чтение CSV/Excel-файлов
Параметры HTTP-запросов
Десериализация JSON

Способы исправления и защиты кода

Универсального «лекарства» нет — выбор приёма зависит от того, насколько вы доверяете источнику данных. Ниже — проверенные подходы от простого к сложному.

  • 🧹 Предварительная очистка — удалить пробелы и разделители: value.strip().replace(" ", "").replace(",", ".") перед парсингом дробных чисел.
  • Валидация регулярным выражением — проверить строку шаблоном "-?\\d+" для целых чисел до вызова parseInt().
  • 🛡️ Обработка через try-catch — перехватить исключение и подставить значение по умолчанию или вернуть пользователю понятное сообщение.
  • 📦 Безопасный метод-обёртка — написать утилиту, возвращающую Optional<Integer> вместо выброса исключения.

Пример безопасной обёртки:

public static Optional<Integer> tryParseInt(String s) {

if (s == null) return Optional.empty();

try {

return Optional.of(Integer.parseInt(s.strip()));

} catch (NumberFormatException e) {

return Optional.empty();

}

}

☑️ Чек-лист перед парсингом строки в число

Выполнено: 0 / 5
⚠️ Внимание: не используйте перехват NumberFormatException как основной механизм валидации в «горячих» участках кода. Создание исключения — относительно дорогая операция, и в циклах с миллионами итераций это заметно скажется на производительности. Для массовой обработки предпочтительнее предварительная проверка регулярным выражением.

Локаль и десятичные разделители

Один из самых коварных сценариев — парсинг дробных чисел. Метод Double.parseDouble() принимает только точку как десятичный разделитель и не учитывает локаль. Поэтому строка "12,5", типичная для русской или немецкой локали, гарантированно вызовет исключение.

Если данные приходят в локализованном формате, корректное решение — использовать NumberFormat с явным указанием локали:

NumberFormat fmt = NumberFormat.getInstance(new Locale("ru", "RU"));

Number n = fmt.parse("12,5"); // корректно распарсится как 12.5

Обратный подход — жёстко зафиксировать «машинный» формат данных на этапе проектирования: договориться, что все API и файлы используют точку и не содержат разделителей тысяч. Требование единого формата чисел на границах системы устраняет целый класс ошибок парсинга ещё до их появления.

💡

При чтении CSV-файлов из Excel проверяйте, не преобразовал ли Excel числа в текст с неразрывными пробелами или апострофами. Откройте файл в текстовом редакторе (не в Excel) и посмотрите на сырые данные.

Переполнение и выбор числового типа

Менее очевидная причина исключения — переполнение. Строка "3000000000" состоит только из цифр, но не помещается в int (максимум 2 147 483 647), и Integer.parseInt() выбросит то же самое NumberFormatException. Сообщение об ошибке при этом не скажет, что дело именно в диапазоне.

ТипМетод парсингаДиапазон / особенности
intInteger.parseInt()примерно ±2,1 млрд
longLong.parseLong()примерно ±9,2×10¹⁸
doubleDouble.parseDouble()только точка как разделитель
BigIntegernew BigInteger(s)произвольная точность, тоже бросает NumberFormatException
BigDecimalnew BigDecimal(s)точные десятичные значения, только точка

Если заранее неизвестен порядок чисел (например, идентификаторы из внешней системы), безопаснее парсить в long или BigInteger, а затем при необходимости проверять границы. Метод Integer.decode(), кстати, принимает шестнадцатеричные (0x1F) и восьмеричные записи — полезно, если формат входных данных нестрогий.

Почему parseInt(null) бросает NumberFormatException, а не NullPointerException

Таково задокументированное поведение метода Integer.parseInt: спецификация определяет, что строка null рассматривается как некорректное числовое значение, поэтому выбрасывается NumberFormatException. Это историческое решение сохраняется во всех версиях Java. На практике это значит, что проверку на null нужно делать явно, до вызова парсинга, иначе причина сбоя будет замаскирована.

Типичные ошибки при исправлении

Разработчики, впервые столкнувшись с исключением, нередко выбирают решения, которые лишь маскируют проблему. Стоит знать о подводных камнях.

⚠️ Внимание: «молчаливый» блок catch (NumberFormatException e) {} без логирования — худший вариант обработки. Ошибка исчезнет из консоли, но данные будут теряться незаметно. Как минимум записывайте проблемное значение в лог, иначе следующая диагностика станет невозможной.

Ещё одна распространённая ошибка — замена запятой на точку через replace(",", ".") без анализа данных. Если в строке окажется разделитель тысяч ("1,234,567" в американском формате), результат будет искажён без всякого исключения — а это хуже, чем явный сбой. Вам нужно сначала определить реальный формат источника, и только потом выбирать стратегию нормализации.

Наконец, не стоит парсить в double денежные суммы и другие значения, где важна точность: двоичное представление дробей приводит к ошибкам округления. Для финансовых расчётов стандартом является BigDecimal.

💡

Правильная стратегия: валидируйте данные на входе, логируйте исходные значения при сбоях и выбирайте числовой тип с запасом по диапазону.

Часто задаваемые вопросы

Что означает «For input string: ""» с пустой строкой?

В программу пришла пустая строка — например, пользователь не заполнил поле формы, а код всё равно вызвал parseInt(). Проверяйте входные данные на пустоту (isEmpty() или isBlank()) до парсинга и задавайте значение по умолчанию.

Чем NumberFormatException отличается от ClassCastException?

NumberFormatException возникает при преобразовании строки в число, когда формат строки некорректен. ClassCastException — при попытке привести уже существующий объект одного типа к несовместимому типу. Это разные механизмы: первый о текстовом представлении, второй об иерархии типов.

Как распарсить число с пробелами-разделителями тысяч, например "1 000 000"?

Удалите разделители перед парсингом: s.replace(" ", "").replace("\u00A0", "") — важно удалить и обычные, и неразрывные пробелы. Альтернатива — NumberFormat.getInstance(locale).parse(s) с локалью, где такой формат принят.

Можно ли узнать позицию ошибочного символа в строке?

Стандартное исключение такой информации не содержит — только саму строку. Если нужна точная позиция, используйте NumberFormat.parse() с объектом ParsePosition или валидируйте строку посимвольно собственным кодом.

Почему в Android-приложении ошибка возникает только у части пользователей?

Наиболее вероятная причина — разные региональные настройки устройств. На телефонах с локалью, где десятичный разделитель — запятая, введённые или сгенерированные строки могут не соответствовать формату, который ожидает parseDouble(). Форматируйте и парсите числа с явно заданной локалью, не полагаясь на системную.