以下代码抛出NullPointerException
:
int num = Integer.getInteger("123");
我的编译器是否在null上调用getInteger
,因为它是静态的?这没有任何意义!
发生了什么事?
答案 0 :(得分:202)
这里有两个问题:
Integer getInteger(String)
不符合您的想法
null
Integer
到int
的分配会导致自动取消装箱
Integer
为null
,因此会引发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
方法有关。
不可否认,这可能是一个惊喜。不幸的是,图书馆有这样的惊喜,但它确实教给你一个宝贵的教训:总是查阅文档以确认方法的作用。
同样地,Return of the Puzzlers: Schlock and Awe (TS-5186),Josh Bloch和Neal Gafter的2009 JavaOne技术会议演示文稿中提到了这个问题的变体。以下是结论幻灯片:
道德
- 图书馆潜藏着奇怪而可怕的方法
- 有些人有无害的名字
- 如果您的代码行为不当
- 确保您正在调用正确的方法
- 阅读图书馆文档
- 对于API设计师
- 不要违反最不惊讶的原则
- 不要违反抽象层次结构
- 不要对不同的行为使用相似的名称
为了完整起见,还有一些类似于Integer.getInteger
的方法:
另一个问题当然是NullPointerException
被抛出的方式。要关注此问题,我们可以按如下方式简化代码段:
Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!
以下是Effective Java 2nd Edition的引用,第49项:将原始类型更喜欢盒装基元:
总之,只要有选择,就可以优先使用原始元素。原始类型更简单,更快捷。如果你必须使用盒装基元,小心!自动装箱减少了使用盒装基元的冗长,但没有降低危险。当您的程序将两个盒装基元与
==
运算符进行比较时,它会进行身份比较,这几乎肯定不是您想要的。当您的程序执行涉及盒装和未装箱原语的混合类型计算时,它会进行拆箱,当您的程序取消装箱时,它可以抛出NullPointerException
。最后,当您的程序框原始值时,它可能导致代价高昂且不必要的对象创建。
有些地方你别无选择,只能使用盒装基元,例如:泛型,但除此之外你应该认真考虑是否有合理使用盒装基元的决定。
答案 1 :(得分:15)
来自http://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.html:
getInteger'确定具有指定名称的系统属性的整数值。'
你想要这个:
Integer.parseInt("123")
答案 2 :(得分:5)
请检查方法getInteger()的文档。
在此方法中,String
参数是一个系统属性,用于确定具有指定名称的系统属性的整数值。 “123”不是任何系统属性的名称,如here所述。
如果要将此String转换为int
,请将该方法用作
int num = Integer.parseInt("123")
。