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

use*_*886 100 java autoboxing integer api-design nullpointerexception

以下代码抛出NullPointerException:

int num = Integer.getInteger("123");
Run Code Online (Sandbox Code Playgroud)

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

发生了什么?

pol*_*nts 207

大图

这里有两个问题:

  • Integer getInteger(String) 不会做你认为它做的事情
    • null在这种情况下它返回
  • 从分配Integerint原因自动拆箱
    • 既然Integernull,NullPointerException就抛出了

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

参考

Integer API参考


Integer.getInteger

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

public static Integer getInteger(String nm):确定具有指定名称的系统属性的整数值.如果没有具有指定名称的属性,如果指定的名称为空null,或者如果属性没有正确的数字格式,则null返回.

换句话说,这种方法没有任何关系解析String到一个int/Integer值,而是它与做的System.getProperty方法.

不可否认,这可能是一个惊喜.不幸的是,图书馆有这样的惊喜,但它确实教给你一个宝贵的教训:总是查阅文档以确认方法的作用.

同样,这个问题的一个变种出现在Puzzlers的回归:Schlock和Awe(TS-5186),Josh Bloch和Neal Gafter的2009 JavaOne技术会议演讲中.这是结束幻灯片:

道德

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

为了完整起见,还有以下类似的方法Integer.getInteger:

相关问题


在自动装箱

当然,另一个问题是如何NullPointerException抛出.要关注此问题,我们可以按如下方式简化代码段:

Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!
Run Code Online (Sandbox Code Playgroud)

以下是Effective Java 2nd Edition的引用,第49项:首选原始类型为盒装基元:

总之,只要您有选择,就可以使用原始优先于盒装原语.原始类型更简单,更快捷.如果你必须使用盒装基元,小心!自动装箱减少了使用盒装基元的冗长,但没有降低危险.当您的程序将两个盒装基元与==运算符进行比较时,它会进行身份比较,这几乎肯定不是您想要的.当你的程序进行涉及盒装和未装箱原语的混合型计算时,它会进行拆箱,当你的程序进行拆箱时,它就会抛出NullPointerException.最后,当您的程序框原始值时,它可能导致代价高昂且不必要的对象创建.

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

相关问题

  • 所以`Integer.getInteger(s)`大致相当于`Integer.parseInt(System.getProperty(s))`?我认为我更喜欢第二个,即使它更冗长,因为它突出了你从系统属性中提取信息的事实. (10认同)
  • 我发布那条评论后,我意识到我只能看看Integer类的实际来源!我在正确的轨道上,除了它使用`Integer.decode`而不是`Integer.parseInt`,它寻找一个前导的"0x"或"0"来分别将数字解析为十六进制或八进制. (5认同)
  • @Oracle 你能弃用 java.lang.Integer.getInteger(String) 吗? (2认同)

Kie*_*one 16

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

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

你要这个:

Integer.parseInt("123")
Run Code Online (Sandbox Code Playgroud)


小智 6

请检查方法getInteger()的文档.在此方法中,String参数是一个系统属性,用于确定具有指定名称的系统属性的整数值."123"是没有任何系统属性的名称,如讨论在这里.如果要将此String转换为int,请将该方法用作 int num = Integer.parseInt("123").