Перейти к основному содержимому

Проверить значение null перед вызовом Parse в Double.parseDouble

· 5 мин. чтения

Задача: Наибольшая подстрока палиндром

Для заданной строки s, верните наибольшую подстроку палиндром входящую в s. Подстрока — это непрерывная непустая последовательность символов внутри строки. Стока является палиндромом, если она читается одинаково в обоих направлениях...

ANDROMEDA 42

1. Обзор

При преобразовании Java String в double мы обычно используем метод Double.parseDouble (String value) . Этот метод позволяет нам преобразовать строковое представление данного двойного числа — например, «2.0» — в примитивное двойное значение.

Как и в случае с большинством вызовов методов, рекомендуется избегать передачи нулевой ссылки, которая, скорее всего, приведет к исключению NullPointerException во время выполнения.

В этом руководстве мы рассмотрим несколько способов проверки на null перед вызовом Double.parseDouble . Мы начнем с рассмотрения решений, использующих ядро Java, прежде чем рассматривать некоторые внешние библиотеки.

2. Зачем проверять

Во-первых, давайте разберемся, что произойдет, если мы не будем проверять нулевые значения при разборе строки S. Начнем с передачи пустой строки :

double emptyString = Double.parseDouble("");

Когда мы запустим этот код, он выдаст исключение java.lang.NumberFormatException :

Exception in thread "main" java.lang.NumberFormatException: empty String
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
...

Теперь давайте рассмотрим передачу нулевой ссылки:

double nullString = Double.parseDouble(null);

Неудивительно, что на этот раз будет выброшено исключение java.lang.NullPointerException :

Exception in thread "main" java.lang.NullPointerException
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1838)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
...

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

3. Как проверить с помощью Core Java

В этом разделе мы рассмотрим несколько вариантов проверки нулевых или пустых значений с помощью ядра Java.

3.1. Использование ванильной Java

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

private static double parseStringToDouble(String value) {
return value == null || value.isEmpty() ? Double.NaN : Double.parseDouble(value);
}

Как мы видим, если значение, которое мы пытаемся проанализировать, равно null или пусто, этот метод возвращает не число . В противном случае мы вызываем метод Double.parseDouble .

Мы можем пойти дальше в этом примере и предложить возможность предоставления предопределенного значения по умолчанию :

private static double parseStringToDouble(String value, double defaultValue) {
return value == null || value.isEmpty() ? defaultValue : Double.parseDouble(value);
}

Когда мы вызываем этот метод, мы предоставляем соответствующее значение по умолчанию для возврата, если предоставленное значение равно null или пусто:

assertThat(parseStringToDouble("1", 2.0d)).isEqualTo(1.0d);
assertThat(parseStringToDouble(null, 1.0d)).isEqualTo(1.0d);
assertThat(parseStringToDouble("", 1.0d)).isEqualTo(1.0d);

3.2. Использование опционального

Теперь давайте взглянем на другое решение с использованием Optional :

private static Optional parseStringToOptionalDouble(String value) {
return value == null || value.isEmpty() ? Optional.empty() : Optional.of(Double.valueOf(value));
}

На этот раз мы используем необязательный тип возвращаемого значения . Поэтому, когда мы вызываем этот метод, у нас есть возможность вызвать стандартные методы, такие как isPresent() и isEmpty() , чтобы определить, присутствует ли значение:

parseStringToOptionalDouble("2").isPresent()

Мы также можем вернуть значение по умолчанию, используя метод orElse для Optional :

parseStringToOptionalDouble("1.0").orElse(2.0d) 
parseStringToOptionalDouble(null).orElse(2.0d)
parseStringToOptionalDouble("").orElse(2.0d)

4. Внешние библиотеки

Теперь, когда мы хорошо понимаем, как проверять нулевые и пустые значения с помощью ядра Java, давайте взглянем на некоторые внешние библиотеки.

4.1. Google Гуава

Первое внешнее решение, которое мы рассмотрим, — это Google Guava , которое доступно на Maven Central :

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>

Мы можем просто использовать метод Doubles.tryParse :

Doubles.tryParse(MoreObjects.firstNonNull("1.0", "2.0"))
Doubles.tryParse(MoreObjects.firstNonNull(null, "2.0"))

В этом примере мы также используем метод MoreObjects.firstNonNull , который возвращает первый из двух заданных параметров, не равный null .

Этот код будет работать нормально в большинстве случаев, но давайте представим другой пример:

Doubles.tryParse(MoreObjects.firstNonNull("", "2.0"))

В этом случае, поскольку пустая строка String не равна null , метод вернет null вместо создания исключения NumberFormatException . Мы избегаем исключения, но нам все равно придется обрабатывать нулевое значение в какой-то точке нашего кода приложения.

4.2. Apache Commons Lang NumberUtils

Класс NumberUtils предоставляет множество полезных утилит, облегчающих работу с числами.

Артефакт Apache Commons Lang доступен на Maven Central :

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>

Затем мы можем просто использовать метод toDouble из NumberUtils :

NumberUtils.toDouble("1.0")
NumberUtils.toDouble("1.0", 1.0d)

Здесь у нас есть два варианта:

  • Преобразовать String в double , возвращая 0.0d , если преобразование не удалось
  • Преобразуйте String в double , предоставив определенное значение по умолчанию, если преобразование завершится ошибкой.

Если мы передаем пустое или нулевое значение, по умолчанию возвращается 0.0d :

assertThat(NumberUtils.toDouble("")).isEqualTo(0.0d);
assertThat(NumberUtils.toDouble(null)).isEqualTo(0.0d);

Это лучше, чем в предыдущем примере, так как мы всегда получаем двойное возвращаемое значение, независимо от того, что происходит во время преобразования.

4.3. Вавр

И последнее, но не менее важное: давайте взглянем на vavr.io , который предлагает функциональный подход .

Как всегда, артефакт можно найти на Maven Central :

<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.10.2</version>
</dependency>

Опять же, мы определим простой метод, использующий класс vavr Try :

public static double tryStringToDouble(String value, double defaultValue) {
return Try.of(() -> Double.parseDouble(value)).getOrElse(defaultValue);
}

Мы будем вызывать этот метод точно так же, как и в других наших примерах:

assertThat(tryStringToDouble("1", 2.0d)).isEqualTo(1.0d);
assertThat(tryStringToDouble(null, 2.0d)).isEqualTo(2.0d);
assertThat(tryStringToDouble("", 2.0d)).isEqualTo(2.0d);

5. Вывод

В этом кратком руководстве мы рассмотрели несколько способов проверки нулевых и пустых строк перед вызовом метода Double.parseDouble .

Как всегда, полный исходный код статьи доступен на GitHub .