以下代码抛出NullPointerException
:
int num = Integer.getInteger("123");
我的编译器是否调用getInteger
null 因为它是静态的?这没有任何意义!
发生了什么?
以下代码抛出NullPointerException
:
int num = Integer.getInteger("123");
我的编译器是否调用getInteger
null 因为它是静态的?这没有任何意义!
发生了什么?
这里有两个问题:
Integer getInteger(String)
不做你认为它做的事
null
在这种情况下它会返回Integer
从to的分配int
导致自动拆箱
Integer
is null
,NullPointerException
被抛出要解析(String) "123"
为(int) 123
,您可以使用 eg int Integer.parseInt(String)
。
Integer
API 参考Integer.getInteger
以下是文档必须说明的有关此方法的作用:
public static Integer getInteger(String nm)
:确定具有指定名称的系统属性的整数值。如果没有具有指定名称的属性,如果指定的名称为空或null
,或者如果属性没有正确的数字格式,则null
返回。
换句话说,此方法与将 a 解析String
为int/Integer
值无关,而是与System.getProperty
方法有关。
诚然,这可能是一个相当大的惊喜。不幸的是,图书馆有这样的惊喜,但它确实教会了你一个宝贵的教训:总是查阅文档以确认方法的作用。
巧合的是,这个问题的一个变体出现在谜题归来: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 条的引述:Prefer primitive types to boxed primitives:
总之,只要您有选择,就优先使用原语而不是盒装原语。原始类型更简单、更快。如果您必须使用盒装图元,请小心!自动装箱减少了使用装箱原语的冗长,但不会降低危险。当您的程序将两个装箱原语与
==
运算符进行比较时,它会进行身份比较,这几乎肯定不是您想要的。当您的程序执行涉及装箱和拆箱原语的混合类型计算时,它会拆箱,而当您的程序拆箱时,它可以抛出NullPointerException
. 最后,当您的程序将原始值装箱时,可能会导致成本高昂且不必要的对象创建。
有些地方你别无选择,只能使用盒装原语,例如泛型,但否则你应该认真考虑使用盒装原语的决定是否合理。
来自http://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.html:
' getInteger '确定具有指定名称的系统属性的整数值。
你要这个:
Integer.parseInt("123")
请检查方法getInteger()的文档。在此方法中,String
参数是一个系统属性,它确定具有指定名称的系统属性的整数值。“123”不是任何系统属性的名称,如此处所述。如果要将此 String 转换为int
,则使用 as 方法
int num = Integer.parseInt("123")
。