陷阱 - 不必要地使用原始包装可能导致 NullPointerExceptions

有时,新 Java 的程序员将交替使用原始类型和包装器。这可能会导致问题。考虑这个例子:

public class MyRecord {
    public int a, b;
    public Integer c, d;
}

...
MyRecord record = new MyRecord();
record.a = 1;               // OK
record.b = record.b + 1;    // OK
record.c = 1;               // OK
record.d = record.d + 1;    // throws a NullPointerException

我们的 MyRecord1 依赖于默认初始化来初始化其字段上的值。因此,当我们记录时,ab 字段将被设置为零,cd 字段将被设置为 null

当我们尝试使用默认的初始化字段时,我们看到 int 字段始终有效,但 Integer 字段在某些情况下有效,而在其他情况下无效。具体来说,在失败的情况下(使用 d),会发生的情况是右侧的表达式尝试取消打开 null 引用,这就是导致 NullPointerException 被抛出的原因。

有几种方法可以看看这个:

  • 如果字段 cd 需要是原始包装器,那么要么我们不应该依赖于默认初始化,要么我们应该测试 null。前者是正确的方法,除非对于 null 状态的字段有明确的含义。

  • 如果字段不需要是原始包装器,那么使它们成为原始包装器是错误的。除了这个问题,原始包装器相对于原始类型还有额外的开销。

这里的教训是不使用原始包装类型,除非你真的需要。

1 - 本类不是良好编码实践的一个例子。例如,精心设计的类不会有公共字段。但是,这不是这个例子的重点。