【问题标题】:Is null typed in Java [duplicate]在 Java 中输入 null [重复]
【发布时间】:2015-05-13 17:29:13
【问题描述】:

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

@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,据我所知 @ 987654328@ 不是有效的primitive 类型。

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

【问题讨论】:

标签: java types null


【解决方案1】:

这个

Boolean.valueOf(nullB)

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

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

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

这个过程在 JLS here中有描述

如果rBoolean 类型的引用,则拆箱转换转换为 r 转为r.booleanValue()

这个

Boolean.valueOf(null)

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

返回一个Boolean,其值由指定字符串表示。 如果字符串参数是,则返回的布尔值表示 true 值 不是null 并且等于字符串"true",忽略大小写。

【讨论】:

    【解决方案2】:

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

    返回一个布尔值,其值由指定字符串表示。 如果字符串参数为 not null 且等于字符串“true”,则返回的布尔值表示一个真值,忽略大小写。

    你传入了一个null,所以它会返回false

    【讨论】:

      【解决方案3】:

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

      15.12.2。编译时步骤 2:确定方法签名

      ...

      1. 第一阶段(第 15.12.2.2 节)执行重载解决方案,不允许装箱或拆箱转换,或使用可变参数方法调用。如果在此阶段未找到适用的方法,则处理继续到第二阶段。

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

      【讨论】:

      • 这个答案一针见血!
      【解决方案4】:

      看一下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)的String参数为null,则返回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 值,它接受TrueFalsenull。由于您传递了 Boolean 值而不是 boolean 值,我想这就是它失败的原因。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-02
        • 2012-09-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多