Java 中是否输入了空值

Is null typed in Java

我在我的代码库中遇到了一个错误,我已经缩小到导致此行为的原因。第一个测试用例失败,而后两个测试用例成功。

@Test
public void testBooleanNull1() {
    Boolean nullB = null;
    assertFalse(Boolean.valueOf(nullB));
}

@Test
public void testBooleanNull2() {
    String nullS = null;
    assertFalse(Boolean.valueOf(nullS));
}
@Test
public void testBooleanNull3() {
    assertFalse(Boolean.valueOf(null));
}

我知道 Boolean.valueOf 是一个重载方法,有两个变体,一个采用 String,另一个采用 boolean.

类型的原语

我怀疑这是由于自动装箱而发生的,但我不确定是否是这种情况,而且我不知道为什么 null 被转换为 Boolean据我所知 null 不是有效的 primitive 类型。

我已经从 Apache Commons 开始使用 BooleanUtils,我在这里问这个是为了更好地理解为什么会这样。

这个

Boolean.valueOf(nullB)

是对 Boolean#valueOf(boolean) 的调用。

它失败了,因为 BooleannullB 的拆箱失败并出现 NullPointerException。也就是说,变成了

boolean val = nullB.booleanValue(); // at runtime nullB stores the value null
Boolean.valueOf(val)

JLS 中描述了这个过程here

If r is a reference of type Boolean, then unboxing conversion converts r into r.booleanValue()

这个

Boolean.valueOf(null)

正在调用 overloaded version that accepts a String (since null 不是 boolean 类型的有效表达式)。

Returns a Boolean with a value represented by the specified string. The Boolean returned represents a true value if the string argument is not null and is equal, ignoring case, to the string "true".

为什么第二个会成功?查看 public static Boolean valueOf(String s) 的文档:

Returns a Boolean with a value represented by the specified string. The Boolean returned represents a true value if the string argument is not null and is equal, ignoring case, to the string "true".

你传入了一个null,所以它会returnfalse

JLS中描述了重载方法解析:

15.12.2. Compile-Time Step 2: Determine Method Signature

...

  1. The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.

在我们的例子中,在 Boolean.valueOf(boolean)Boolean.valueOf(String) 之间进行选择,编译器会选择 valueOf(String),因为它不需要拆箱。

查看 class Boolean

的源代码
public static Boolean valueOf(String s) {
    return toBoolean(s) ? TRUE : FALSE;
}

..然后:

private static boolean toBoolean(String name) {
   return ((name != null) && name.equalsIgnoreCase("true"));
}

如果 Boolean.valueOf(String s) 的字符串参数是 null,它将 return false,因此第二种情况成功。

在第一种情况下,关于使用 Boolean.valueOf 将数据类型作为布尔值,文档说明如下:

public static Boolean valueOf(boolean b)

Returns a Boolean instance representing the specified boolean value. If the specified boolean value is true, this method returns Boolean.TRUE; if it is false, this method returns Boolean.FALSE. If a new Boolean instance is not required, this method should generally be used in preference to the constructor Boolean(boolean), as this method is likely to yield significantly better space and time performance.

Parameters:
b - a boolean value.
Returns:
a Boolean instance representing b.

这里需要的参数是一个 boolean 值,它接受 TrueFalse 而不是 Boolean 值,它接受 True , Falsenull。由于您传递了 Boolean 值而不是 boolean 值,我想这就是它失败的原因。