«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:

  1. Don’t try to convert alphabetic or special characters into numbers – the Java Number API cannot do that.
  2. We may want to validate an input string using regular expressions and throw the exception for the invalid characters.
  3. We can sanitize input against foreseeable known issues with methods like trim() and replaceAll().
  4. 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.