NullPointerException from Boolean

2019-02-16 07:15发布

This is one for the java purists I think. I recently had an issue with a method to perform a custom parsing of String values to a Boolean. A simple enough task, but for some reason the method below was throwing a NullPointerException in the null case...

static Boolean parseBoolean(String s)
{
    return ("1".equals(s) ? true : ("0".equals(s) ? false : null));
}

The return type for the method is Boolean so why or how can a NullPointerException be thrown? From debugging through it seems the exception is being thrown at the point where the nested in-line conditional statement evaluates to null and returns null to the outer in-line conditional, but again I can't explain why.

Eventually I gave up and rewrote the method as follows, which works as expected:

static Boolean parseBoolean(String s)
{
    if ("1".equals(s)) return true;
    if ("0".equals(s)) return false;

    return null;
}

The following code is half way between the two and also works as expected:

static Boolean parseBoolean(String s)
{
    if ("1".equals(s)) return true;

    return "0".equals(s) ? false : null;
}

3条回答
在下西门庆
2楼-- · 2019-02-16 07:41

Interesting but no answer tells you why this happens in the first place.

This has to do with the ternary expression.

The compiler interprets null as a null reference to Boolean, applies the autoboxing/unboxing rules for Boolean (on a null) => you get a NullPointerException at runtime.

查看更多
时光不老,我们不散
3楼-- · 2019-02-16 07:44

My suggestion? Don't return Boolean, return boolean and throw an exception:

static boolean parseBoolean(String s)
{
  if ("1".equals(s)) return true;
  if ("0".equals(s)) return false;

  throw new IllegalArgumentException(s + " is not a boolean value.");
}

Adopting an approach like the above will help avoid you accidentally referencing a null Boolean object.

See the excellent answer from NilsH to see why your original method is throwing an exception.

查看更多
爷、活的狠高调
4楼-- · 2019-02-16 07:53

This also works:

static Boolean parseBoolean(String s)
{
    return ("1".equals(s) ? Boolean.TRUE : ("0".equals(s) ? Boolean.FALSE : null));
}

So the reason you get an NPE is due to autoboxing because using boolean in the ternary operator causes the result of the expression to be treated as a boolean. And un-boxing of null causes an NPE.

查看更多
登录 后发表回答