0

当我执行以下代码时发生了一件奇怪的事情:

private void doStuff(Long inLong) {
    long theNumber = inLong;

    /* ... */
}

有时我在分配行的日志中看到 NullPointerException,但我不明白为什么会发生这种情况。任何想法?

4

6 回答 6

2

你传入了null。检查你传入的内容。

于 2011-09-07T10:12:11.283 回答
2

因为long theNumber = inLong;, inLong 的 long 值是通过隐式调用来获取的inLong.longValue()。这称为自动拆箱(有时更一般的自动装箱)。当 inLong 为 null 时,您将因此得到 NullPointerException,就像在 null 上调用任何其他方法一样。

因此,您应该考虑一些替代方案:

如果您不需要未定义的值,则应确保调用者永远不会传递 null 并通过以下方式断言:

private void doStuff(Long inLong) {
  assert inLong != null; 
  long theNumber = inLong;
  /* ... */
} 

(或使用Nonnull-Checker)。如果该方法是公开的,并且您不能确定没有传递 null,请执行以下操作:

public void doStuff(Long inLong) {
  if (inLong == null) { throw new IllegalArgumentException(); } 
  long theNumber = inLong;
  /* ... */
} 

如果您既不需要未定义的值,也不需要在集合(或任何其他通用参数)中使用该值,请改用该方法private void doStuff(long inLong)。如果您确实需要 Long 对象,当然,您仍然可以使用 type 的参数long并在内部进行(自动)装箱doStuff以获得相应的 Long 对象。

如果您确实需要未定义的值,您应该检查它并执行必要的操作:

private void doStuff(Long inLong) {
  if (inLong == null) { 
    handleUndef(); 
  } else {
    long theNumber = inLong;
    /* ... */
  }
} 

在我看来,仅将值设置为 0 而不是更详细的值handleUndef()是可疑的,因为那时您可以首先使用 long 类型的参数(见上文)。

于 2011-09-07T10:17:04.397 回答
1

inLong 大概是null. 然后您尝试分配一个null引用并将其拆箱为原始类型。

于 2011-09-07T10:12:03.120 回答
1

因为inLong可以为null,不会自动映射到0。
我猜你想要做的是:

theNumber = 0; // or Long.MIN_VALUE or Long.MAX_VALUE or whatever you prefer
if (inLong != null) {
    theNumber = inLong;
}
// ... 
于 2011-09-07T10:14:10.117 回答
0

那是因为 inLong 参数为空。每当您将Long对象分配给long变量时,Java 都会自动尝试将其拆箱为正确的类型,但如果 Long 变量的值为 null,则会失败。

只需在该分配之前进行一次空检查,您就会摆脱该错误,但您可能必须引发异常或适当地处理空参数。

于 2011-09-07T10:15:03.583 回答
0

如果 inLong 为空,则 NPE 是预期的行为。

long theNumber = inLong;

在语义上等价于

long theNumber = inLong.longValue();

这应该使 NPE 的原因显而易见。

于 2011-09-07T10:18:56.037 回答