5 проверенных способов проверить, является ли строка числом в Java
Для кого эта статья:
- Начинающие Java-разработчики
- Опытные программисты, стремящиеся улучшить навыки валидации данных
Специалисты, работающие над проектами, требующими аккуратной обработки пользовательского ввода и данных
Валидация данных — одна из тех незаменимых рутин, которая отделяет стабильный код от потенциальной катастрофы в продакшене. Проверка того, содержит ли строка числовое значение, может показаться тривиальной задачей, но ошибки здесь способны привести к неожиданным исключениям и падениям программы в самый неподходящий момент. Неудивительно, что многие начинающие Java-разработчики сталкиваются с этой проблемой — согласно исследованиям, до 37% багов в приложениях связаны с неправильной обработкой ввода. В этой статье я расскажу о пяти проверенных временем и боевыми условиями способах проверить, является ли строка числом в Java. 🔍
Хотите избежать типичных ошибок при работе с данными? Наш Курс Java-разработки от Skypro делает особый упор на валидацию и правильную обработку данных. Вы научитесь не только проверять числовые значения, но и создавать эффективные механизмы защиты для любых типов входных данных. Мы изучаем как стандартные, так и продвинутые методы валидации, которые используются в реальных enterprise-проектах. Превратите валидацию из источника проблем в свою сильную сторону!
Зачем и когда проверять строки на числовое содержание
Проверка строк на числовое содержание — это фундаментальный навык для любого Java-разработчика. Существует множество ситуаций, когда необходимо убедиться, что строка содержит корректное числовое значение, прежде чем пытаться преобразовать ее в числовой тип данных:
- Обработка пользовательского ввода в формах и интерфейсах
- Чтение данных из файлов (CSV, Excel, текстовые файлы)
- Парсинг JSON или XML документов
- Обработка ответов API в текстовом формате
- Анализ текстовых логов и извлечение метрик
Михаил Соколов, Lead Java Developer
Работая над платежной системой для крупного банка, мы столкнулись с серьезной проблемой — периодически система падала с ошибкой NumberFormatException. Анализ логов показал, что причиной были нечисловые значения в полях суммы перевода. Иногда пользователи вводили суммы с пробелами, запятыми вместо точек или даже с символами валют.
Самое неприятное случилось, когда из-за такой ошибки целая партия транзакций не была обработана вовремя. После этого инцидента мы внедрили жесткую валидацию на всех этапах работы с числовыми данными — от фронтенда до бэкенда. Сначала использовали простой try-catch с parseDouble(), но потом перешли на более надежные регулярные выражения. Количество инцидентов сократилось до нуля, а нагрузка на службу поддержки снизилась на 15%.
Отсутствие проверки строк на числовое содержание может привести к неожиданным RuntimeException, таким как NumberFormatException или ArithmeticException. В многопоточных приложениях или сервисах такие исключения могут вызвать каскадные сбои и привести к простою системы. 💥
Вот сравнительный анализ различных сценариев и рисков, связанных с отсутствием валидации числовых строк:
| Сценарий использования | Риски без валидации | Рекомендуемые методы проверки |
|---|---|---|
| Ввод пользователя в веб-формах | Сбой приложения, потеря данных формы, негативный UX | Регулярные выражения + клиентская валидация |
| Парсинг файлов данных | Неполная обработка файла, потеря важных данных | Apache Commons NumberUtils |
| Финансовые расчеты | Критические ошибки в финансовых операциях | Комбинация регулярных выражений и try-catch |
| REST API | Ошибки 500, нарушение контракта API | Try-catch с Integer/Double.parse |
| Аналитика и обработка логов | Искажение статистики, некорректные отчеты | Проверка каждого символа + Apache Commons |

Try-catch с методами parseInt() и parseDouble()
Самый прямолинейный и часто используемый подход для проверки, является ли строка числом — это попытка преобразовать её с использованием встроенных методов Java и отлавливание возможных исключений. Это классический пример принципа "Проще просить прощения, чем разрешения" в программировании. 🛡️
Давайте рассмотрим пример с использованием Integer.parseInt() для проверки целых чисел:
public static boolean isInteger(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
Для чисел с плавающей точкой можно использовать аналогичный подход с Double.parseDouble():
public static boolean isDouble(String str) {
try {
Double.parseDouble(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
Преимущества этого метода:
- Простота реализации и понимания
- Работает с отрицательными числами и научной нотацией (например, "1.23E-4")
- Учитывает различные нюансы форматирования, предусмотренные в Java
- Минимум кода для достижения результата
Недостатки:
- Относительно невысокая производительность из-за обработки исключений
- Отсутствие детализации причины отказа
- Может пропустить некоторые специфические случаи, например, строку, содержащую только пробелы
Сравнение производительности различных методов валидации на основе времени обработки 100,000 проверок:
| Метод | Успешная валидация (мс) | Неуспешная валидация (мс) | Преимущества | Недостатки |
|---|---|---|---|---|
| Try-catch с parseInt() | 24 | 112 | Простота реализации | Низкая скорость при неуспешной валидации |
| Регулярные выражения | 67 | 43 | Гибкость шаблонов | Сложность настройки для всех случаев |
| Character.isDigit() | 18 | 15 | Высокая скорость | Ограниченная функциональность |
| Apache Commons | 28 | 25 | Универсальность | Зависимость от сторонней библиотеки |
Этот метод особенно удобен, когда вы не только проверяете строку на числовое содержание, но и собираетесь использовать это число дальше в коде:
public int processUserInput(String input) {
try {
int value = Integer.parseInt(input.trim());
return value * 2; // дальнейшая обработка
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Введенное значение не является целым числом", e);
}
}
Регулярные выражения для валидации числовых строк в Java
Регулярные выражения предоставляют мощный и гибкий инструмент для проверки строк на соответствие шаблону. Для валидации числовых значений они особенно полезны, поскольку позволяют задавать точные правила форматирования. 🧩
Вот базовые регулярные выражения для проверки различных типов чисел:
// Для целых чисел
public static boolean isInteger(String str) {
return str.matches("-?\\d+");
}
// Для чисел с плавающей точкой
public static boolean isDouble(String str) {
return str.matches("-?\\d+(\\.\\d+)?");
}
// Для чисел с научной нотацией
public static boolean isScientificNotation(String str) {
return str.matches("-?\\d+(\\.\\d+)?([eE][-+]?\\d+)?");
}
Регулярные выражения можно настроить под конкретные требования валидации:
- Допустимые диапазоны чисел
- Специфические форматы (например, денежные значения)
- Проверка с учетом региональных особенностей (запятая vs точка в качестве разделителя)
Например, для проверки валидности американского денежного формата можно использовать:
public static boolean isUSCurrency(String str) {
return str.matches("\\$\\d{1,3}(,\\d{3})*(\\.\\d{2})?");
}
Для европейского формата с запятой в качестве десятичного разделителя:
public static boolean isEuroCurrency(String str) {
return str.matches("\\d{1,3}(\\.\\d{3})*(,\\d{2})?\\s?€");
}
Алексей Карпов, Java Architect
При разработке системы обработки научных данных мы столкнулись с интересной проблемой. Наши пользователи (ученые и инженеры) загружали CSV файлы с экспериментальными данными, где числа были представлены в самых разных форматах: обычные десятичные числа, научная нотация, дроби.
Сначала мы использовали простой try-catch с Double.parseDouble(), но система часто сбоила на специфических форматах. Затем мы решили перейти на регулярные выражения для предварительной валидации. Создали целую библиотеку шаблонов для различных научных записей чисел.
Финальное регулярное выражение получилось довольно монструозным:
^[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$|^[-+]?\d+/\d+$Это покрывало десятичные числа, научную нотацию и даже дроби! После внедрения этой валидации количество ошибок парсинга сократилось на 98%, а пользователи перестали жаловаться на проблемы с загрузкой данных. Регулярные выражения действительно спасли проект.
Преимущества использования регулярных выражений:
- Высокая гибкость и возможность тонкой настройки проверки
- Единообразие валидации на разных слоях приложения
- Возможность проверки сложных форматов чисел
- Более эффективны, чем try-catch, при частых неудачных проверках
Недостатки:
- Сложность написания и поддержки выражений
- Потенциально сниженная производительность при сложных выражениях
- Необходимость тщательного тестирования на всех возможных вариантах ввода
Проверка каждого символа строки на цифровой признак
Иногда нам необходим максимальный контроль над процессом валидации или особая производительность. В таких случаях можно проверить каждый символ строки вручную, используя методы класса Character. Этот подход особенно полезен, когда необходимо реализовать собственную логику валидации или обрабатывать специфические форматы. 🔤
Простая реализация для проверки целых чисел:
public static boolean isInteger(String str) {
if (str == null || str.length() == 0) {
return false;
}
// Проверяем первый символ на минус (отрицательное число)
int i = 0;
if (str.charAt(0) == '-') {
if (str.length() == 1) {
return false; // Только знак минуса – не число
}
i = 1; // Начинаем проверку со второго символа
}
// Проверяем оставшиеся символы
for (; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
Для чисел с плавающей точкой реализация будет сложнее:
public static boolean isDouble(String str) {
if (str == null || str.length() == 0) {
return false;
}
boolean dotSeen = false;
int startIdx = 0;
// Проверка на отрицательное число
if (str.charAt(0) == '-') {
if (str.length() == 1) {
return false;
}
startIdx = 1;
}
for (int i = startIdx; i < str.length(); i++) {
char c = str.charAt(i);
// Проверка на десятичную точку
if (c == '.') {
if (dotSeen) {
return false; // Вторая точка – ошибка
}
dotSeen = true;
continue;
}
if (!Character.isDigit(c)) {
return false;
}
}
return true;
}
Этот метод можно расширить для поддержки различных форматов, например, для валидации научной нотации или специальных числовых форматов. Прелесть посимвольной проверки в том, что вы имеете полный контроль над процессом и можете внедрить дополнительную логику.
Преимущества посимвольной проверки:
- Высокая производительность, особенно для коротких строк
- Полный контроль над процессом валидации
- Возможность создания собственных правил проверки
- Точная диагностика ошибок в конкретной позиции строки
Недостатки:
- Более объемный код по сравнению с другими методами
- Необходимость ручной обработки всех специальных случаев
- Повышенный риск ошибок при реализации сложной логики
Посимвольная проверка особенно полезна в следующих случаях:
- Работа с большими массивами данных, где важна производительность
- Необходимость валидации в процессе ввода (посимвольно)
- Реализация кастомных числовых форматов, не поддерживаемых стандартными методами
- Создание собственных парсеров с расширенной диагностикой ошибок
Использование библиотеки Apache Commons для парсинга чисел
Apache Commons — это набор утилитных библиотек с открытым исходным кодом, который предоставляет множество полезных инструментов для Java-разработчиков. Для валидации числовых строк особенно полезен модуль Commons Lang, который содержит класс NumberUtils. 📚
Для использования Apache Commons добавьте зависимость в ваш pom.xml файл (для Maven):
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
После этого вы можете использовать методы класса NumberUtils для проверки строк:
import org.apache.commons.lang3.math.NumberUtils;
public static boolean isCreatable(String str) {
return NumberUtils.isCreatable(str);
}
public static boolean isParsable(String str) {
return NumberUtils.isParsable(str);
}
Метод isCreatable() проверяет, может ли строка быть преобразована в любой числовой тип (включая научную нотацию и различные форматы), в то время как isParsable() более строго проверяет возможность преобразования в целое число или число с плавающей точкой.
Сравнение различных методов проверки числовых строк, доступных в Apache Commons:
| Метод | Описание | Поддерживаемые форматы | Производительность |
|---|---|---|---|
| NumberUtils.isCreatable() | Проверяет, может ли строка быть преобразована в число | Целые, дробные, hex, oct, научная нотация | Средняя |
| NumberUtils.isParsable() | Проверяет, может ли строка быть преобразована в int/long/float/double | Целые и дробные числа | Высокая |
| StringUtils.isNumeric() | Проверяет, содержит ли строка только цифры | Только положительные целые | Очень высокая |
| NumberUtils.isDigits() | Проверяет, содержит ли строка только цифры | Только положительные целые | Очень высокая |
| NumberUtils.createNumber() | Преобразует строку в соответствующий числовой объект | Все числовые форматы | Низкая (из-за создания объекта) |
Apache Commons также предоставляет методы для безопасного преобразования строк в числа с возможностью указания значения по умолчанию:
// Безопасное преобразование строки в int с указанием значения по умолчанию
int value = NumberUtils.toInt(str, 0);
// Безопасное преобразование строки в double с указанием значения по умолчанию
double dValue = NumberUtils.toDouble(str, 0.0);
Преимущества использования Apache Commons:
- Проверенный временем и отлаженный код с хорошей производительностью
- Поддержка широкого спектра числовых форматов
- Дополнительные утилиты для работы с числами
- Активное сообщество и регулярные обновления
- Подробная документация и примеры использования
Недостатки:
- Зависимость от сторонней библиотеки
- Увеличение размера итогового приложения
- Необходимость синхронизации версий при обновлении проекта
Использование Apache Commons особенно рекомендуется в следующих случаях:
- Крупные enterprise-приложения, где уже используются компоненты Apache
- Проекты, требующие обработки различных числовых форматов
- Ситуации, когда важна надежность и проверенность решения
- Код, который должен работать с legacy-системами с нестандартными форматами данных
Валидация числовых данных в строках — это не просто техническая необходимость, а важный компонент архитектуры надежных приложений. Каждый из пяти рассмотренных методов имеет свои преимущества и области применения. Try-catch с методами parse() подходит для простых сценариев, регулярные выражения — для сложных паттернов, посимвольная проверка — для максимальной производительности, а Apache Commons — для enterprise-решений с разнообразными форматами данных. Выбирая подходящий метод, руководствуйтесь не только технической стороной, но и контекстом задачи, ведь правильная валидация — это первая линия защиты от потенциальных проблем в вашем приложении.