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 .