Check for null Before Calling Parse in Double.parseDouble – 在Double.parseDouble中调用Parse前检查是否为空

最后修改: 2020年 2月 25日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

When converting a Java String to a double, we’ll typically use the Double.parseDouble(String value) method. This method allows us to convert a String representation of a given double – for example, “2.0” – to a primitive double value.

将Java String转换为double时,我们通常会使用Double.parseDouble(String value)方法。这个方法允许我们将给定的doubleString表示–例如,”2.0″–转换成原始的double值。

As with most method calls, it’s good practice to avoid passing a null reference, which will likely result in a NullPointerException at runtime.

与大多数方法调用一样,避免传递一个null引用是一个好的做法。这可能会导致在运行时出现NullPointerException

In this tutorial, we’ll explore several ways we can check for null before invoking Double.parseDouble. We’ll start by considering solutions using core Java before looking at some external libraries.

在本教程中,我们将探讨在调用Double.parseDouble之前检查null的几种方法。在查看一些外部库之前,我们将首先考虑使用核心 Java 的解决方案。

2. Why Check

2.为什么要检查

First, let’s understand what happens if we don’t check for null values when parsing a String. Let’s begin by passing an empty String:

首先,让我们了解一下如果我们在解析String时不检查null值会怎样。让我们从传递一个空的String开始。

double emptyString = Double.parseDouble("");

When we run this code, it will throw a java.lang.NumberFormatException:

当我们运行这段代码时,它将抛出一个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)
	...

Now let’s consider passing a null reference:

现在让我们考虑传递一个null引用。

double nullString = Double.parseDouble(null);

Unsurprisingly, a java.lang.NullPointerException will be thrown this time:

不出所料,这次会抛出一个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)
	...

As we know, it can be good practice to use exceptions in our application code. But in general, we should avoid these kinds of unchecked exceptions, which are likely the result of a programming error.

正如我们所知,在我们的应用代码中使用异常可能是一个好的做法。但一般来说,我们应该避免这类unchecked异常,它们很可能是编程错误的结果

3. How to Check With Core Java

3.如何用Core Java检查

In this section, we’ll take a look at several options to check for null or empty values using core Java.

在本节中,我们将看一下使用核心Java检查null或空值的几个选项。

3.1. Using Vanilla Java

3.1. 使用Vanilla Java

Let’s start by defining a simple method that will check if the value we pass is null or an empty String:

让我们从定义一个简单的方法开始,该方法将检查我们传递的值是否为null或空String

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

As we can see, if the value we are trying to parse is null or empty this method returns not a number. Otherwise, we invoke the Double.parseDouble method.

我们可以看到,如果我们要解析的值是null或空的,这个方法就会返回不是一个数字。否则,我们调用Double.parseDouble方法。

We can take this example a step further and offer the possibility of supplying a predefined default:

我们可以在这个例子中更进一步,提供提供一个预定义的默认值的可能性

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

When we invoke this method, we supply an appropriate default to return if the supplied value is null or empty:

当我们调用这个方法时,如果提供的值是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. Using Optional

3.2.使用Optional

Now let’s take a look at a different solution with the usage of Optional:

现在让我们来看看一个不同的解决方案,使用Optional

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

This time, we’re using Optional as a return type. Therefore, when we invoke this method, we then have the possibility to call standard methods such as isPresent() and isEmpty() to determine if a value is present:

这一次,我们使用Optional作为返回类型。因此,当我们调用这个方法时,我们就有可能调用诸如isPresent()isEmpty()等标准方法来确定一个值是否存在。

parseStringToOptionalDouble("2").isPresent()

We can also return a default value using the orElse method of Optional:

我们还可以使用OptionalorElse方法返回一个默认值。

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

4. External Libraries

4.外部图书馆

Now that we have a good understanding of how to check for null and empty values using core Java, let’s take a look at some external libraries.

现在我们对如何使用核心Java检查null和空值有了很好的理解,让我们看看一些外部库。

4.1. Google Guava

4.1.Google Guava

The first external solution we’ll look at is Google Guava, which is available on Maven Central:

我们要看的第一个外部解决方案是Google Guava,它可以在Maven Central上找到。

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

We can simply use the Doubles.tryParse method:

我们可以简单地使用Doubles.tryParse方法。

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

In this example, we also use the MoreObjects.firstNonNull method, which will return the first of two given parameters that is not null.

在这个例子中,我们还使用了MoreObjects.firstNonNull方法,它将返回两个给定参数中第一个不为null的参数。

This code will work fine in most cases, but let’s imagine a different example:

这段代码在大多数情况下都能正常工作,但让我们想象一个不同的例子。

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

In this case, since the empty String isn’t null, the method will return null instead of throwing a NumberFormatException. We avoid the exception, but we’ll still have to handle a null value at some point in our application code.

在这种情况下,由于空的String不是null,该方法将返回null而不是抛出NumberFormatException我们避免了异常,但是我们仍然必须在我们的应用代码中的某个时刻处理一个null值。

4.2. Apache Commons Lang NumberUtils

4.2.Apache Commons Lang NumberUtils

The NumberUtils class provides many useful utilities that make it easier to work with numbers.

NumberUtils类提供了许多有用的工具,使其更容易处理数字。

The Apache Commons Lang artifact is available from Maven Central:

Apache Commons Lang工件可从Maven Central获得。

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

Then we can simply use the method toDouble from NumberUtils:

那么我们可以简单地使用toDouble方法,该方法来自NumberUtils

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

Here, we have two options:

在这里,我们有两个选择。

  • Convert a String to a double, returning 0.0d if the conversion fails
  • Convert a String to a double, providing a defined default value if the conversion fails

If we pass an empty or null value, 0.0d is returned by default:

如果我们传递一个空或值,默认返回0.0d

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

This is better than the previous example, as we always get a double return value no matter what happens during the conversion.

这比之前的例子要好,因为无论在转换过程中发生什么,我们都会得到一个double返回值。

4.3. Vavr

4.3.Vavr

Last, but not least, let’s take a look at vavr.io, which offers a functional approach.

最后,但并非最不重要,让我们看看vavr.io,它提供了一种功能性方法

As always, the artifact can be found on Maven Central:

一如既往,该工件可以在Maven Central上找到。

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

Again, we’ll define a simple method that makes use of the vavr Try class:

同样,我们将定义一个简单的方法,利用vavr的Try类。

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

We’ll invoke this method in exactly the same way as in our other examples:

我们将以与其他例子中完全相同的方式调用这个方法。

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

5. Conclusion

5.总结

In this quick tutorial, we’ve explored several ways of checking for null and empty strings before invoking the Double.parseDouble method.

在这个快速教程中,我们探讨了在调用Double.parseDouble方法之前检查null和空字符串的几种方法。

As always, the full source code of the article is available over on GitHub.

一如既往,文章的完整源代码可在GitHub上获得