«1. Введение
Java генерирует NumberFormatException — непроверенное исключение — когда не может преобразовать строку в числовой тип.
Так как это не проверено, Java не заставляет нас обрабатывать или объявлять его.
В этом кратком руководстве мы опишем и продемонстрируем, что вызывает исключение NumberFormatException в Java и как его избежать или справиться с ним.
2. Причины исключения NumberFormatException
Существуют различные проблемы, вызывающие исключение NumberFormatException. Например, некоторые конструкторы и методы в Java вызывают это исключение.
Мы обсудим большинство из них в разделах ниже.
2.1. Нечисловые данные, переданные в конструктор
Давайте рассмотрим попытку создания объекта Integer или Double с нечисловыми данными.
Обе эти инструкции вызовут исключение NumberFormatException:
Integer aIntegerObj = new Integer("one");
Double doubleDecimalObj = new Double("two.2");
Давайте посмотрим на трассировку стека, которую мы получили, когда мы передали неверный ввод «one» конструктору Integer в строке 1:
Exception in thread "main" java.lang.NumberFormatException: For input string: "one"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.<init>(Integer.java:867)
at MainClass.main(MainClass.java:11)
Он выдал NumberFormatException . Конструктор Integer потерпел неудачу при попытке понять ввод с помощью parseInt() внутренне.
Java Number API не преобразует слова в числа, поэтому мы можем исправить код, просто изменив его на ожидаемое значение:
Integer aIntegerObj = new Integer("1");
Double doubleDecimalObj = new Double("2.2");
2.2. Анализ строк, содержащих нечисловые данные
Подобно поддержке Java для анализа в конструкторе, у нас есть специальные методы анализа, такие как parseInt(), parseDouble(), valueOf() и decode().
Если мы попытаемся сделать то же самое преобразование с этими:
int aIntPrim = Integer.parseInt("two");
double aDoublePrim = Double.parseDouble("two.two");
Integer aIntObj = Integer.valueOf("three");
Long decodedLong = Long.decode("64403L");
Тогда мы увидим такое же ошибочное поведение.
И мы можем исправить их аналогичным образом:
int aIntPrim = Integer.parseInt("2");
double aDoublePrim = Double.parseDouble("2.2");
Integer aIntObj = Integer.valueOf("3");
Long decodedLong = Long.decode("64403");
2.3. Передача строк с посторонними символами
Или, если мы попытаемся преобразовать строку в число с посторонними данными во входных данных, такими как пробелы или специальные символы:
Short shortInt = new Short("2 ");
int bIntPrim = Integer.parseInt("_6000");
Тогда у нас будет та же проблема, что и раньше.
Мы могли бы исправить это, немного поработав со строкой:
Short shortInt = new Short("2 ".trim());
int bIntPrim = Integer.parseInt("_6000".replaceAll("_", ""));
int bIntPrim = Integer.parseInt("-6000");
Обратите внимание, что здесь, в строке 3, допускаются отрицательные числа, используя символ дефиса в качестве знака минус.
2.4. Форматы чисел, зависящие от локали
Давайте рассмотрим особый случай чисел, зависящих от локали. В европейских регионах запятая может обозначать десятичный разряд. Например, «4000,1» может представлять десятичное число «4000,1».
По умолчанию мы получим NumberFormatException при попытке проанализировать значение, содержащее запятую:
double aDoublePrim = Double.parseDouble("4000,1");
В этом случае нам нужно разрешить запятые и избежать исключения. Чтобы сделать это возможным, Java должна понимать запятую здесь как десятичную.
Мы можем разрешить запятые для европейского региона и избежать исключения, используя NumberFormat.
Давайте посмотрим на это в действии, используя Локаль для Франции в качестве примера:
NumberFormat numberFormat = NumberFormat.getInstance(Locale.FRANCE);
Number parsedNumber = numberFormat.parse("4000,1");
assertEquals(4000.1, parsedNumber.doubleValue());
assertEquals(4000, parsedNumber.intValue());
3. Лучшие практики
Давайте поговорим о нескольких хороших практиках, которые могут помочь нам справиться с NumberFormatException:
- Don’t try to convert alphabetic or special characters into numbers – the Java Number API cannot do that.
- We may want to validate an input string using regular expressions and throw the exception for the invalid characters.
- We can sanitize input against foreseeable known issues with methods like trim() and replaceAll().
- In some cases, special characters in input may be valid. So, we do special processing for that, using NumberFormat, for example, which supports numerous formats.
4 Заключение
В этом руководстве мы обсудили исключение NumberFormatException в Java и его причины. Понимание этого исключения может помочь нам создавать более надежные приложения.
Кроме того, мы научились избегать исключений с некоторыми недопустимыми входными строками.
Наконец, мы рассмотрели несколько рекомендаций по работе с NumberFormatException.
Как обычно, исходный код, использованный в примерах, можно найти на GitHub.