为什么 int num = Integer.getInteger(“123”) 会抛出 NullPointerException?

以下代码抛出:NullPointerException

int num = Integer.getInteger("123");

我的编译器是否调用 null,因为它是静态的?这没有任何意义!getInteger

发生了什么事情?


答案 1

大局观

这里有两个问题在起作用:

  • Integer getInteger(String)不做你认为它做的事情
    • 在这种情况下返回null
  • 从 到 的分配导致自动取消装箱Integerint
    • 由于 is ,则被抛出IntegernullNullPointerException

要解析为 ,您可以使用 例如 .(String) "123"(int) 123int Integer.parseInt(String)

引用

Integer接口引用


Integer.getInteger

以下是文档对此方法的作用的看法:

公共静态 Integer getInteger(String nm):确定具有指定名称的系统属性的整数值。如果没有具有指定名称的属性,如果指定的名称为空或 ,或者如果属性没有正确的数字格式,则返回。nullnull

换句话说,此方法与将 a 解析为值无关,而是与 System.getProperty 方法有关。Stringint/Integer

诚然,这可能是一个惊喜。不幸的是,该库有这样的惊喜,但它确实教会了你一个宝贵的教训:总是查找文档以确认方法的作用。

巧合的是,这个问题的变体出现在《拼图的回归:Schlock and Awe》(TS-5186)、Josh Bloch和Neal Gafter的2009年JavaOne技术会议演讲中。这是最后一张幻灯片:

道德

  • 图书馆里潜伏着奇怪而可怕的方法
    • 有些名字听起来无害
  • 如果您的代码行为异常
    • 确保调用的方法正确
    • 阅读库文档
  • 对于 API 设计人员
    • 不要违反最小惊讶原则
    • 不要违反抽象层次结构
    • 不要对截然不同的行为使用相似的名称

为了完整起见,还有这些方法类似于:Integer.getInteger

相关问题


关于自动取消装箱

当然,另一个问题是如何抛出。为了关注这个问题,我们可以简化代码段,如下所示:NullPointerException

Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!

以下是《有效 Java 第 2 版》第 49 项中的一段话:优先选择基元类型而不是盒装基元:

总之,只要您有选择,就应优先使用带框的基元。基元类型更简单、更快捷。如果必须使用盒装基元,请小心!自动装箱可减少使用装箱基元的详细程度,但不会减少危险。当您的程序将两个盒装基元与运算符进行比较时,它会进行标识比较,这几乎肯定不是您想要的。当您的程序执行涉及盒装和未装箱基元的混合类型计算时,它会取消装箱,而当您的程序执行拆箱时,它可以抛出 .最后,当您的程序框住基元值时,可能会导致昂贵且不必要的对象创建。==NullPointerException

有些地方你别无选择,只能使用盒装基元,例如泛型,但除此之外,你应该认真考虑使用盒装基元的决定是否合理。

相关问题


答案 2

http://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.html

getInteger “确定具有指定名称的系统属性的整数值。

你想要这个:

Integer.parseInt("123")