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

发布于 2024-09-07 02:39:55 字数 194 浏览 1 评论 0原文

以下代码抛出 NullPointerException

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

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

发生什么事了?

The following code throws NullPointerException:

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

Is my compiler invoking getInteger on null since it's static? That doesn't make any sense!

What's happening?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

木格 2024-09-14 02:39:55

总体情况

这里有两个问题:

  • Integer getInteger(String) 没有按照您的想法进行操作
    • 在本例中返回 null
  • Integerint 的赋值会导致自动拆箱
    • 由于Integernull,因此抛出NullPointerException

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

参考文献

Integer API 参考


On Integer.getInteger

这是文档的内容不得不说一下这个方法的作用:

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

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

诚然,这可能是相当令人惊讶的。不幸的是,该库有这样的惊喜,但它确实给您上了宝贵的一课:始终查找文档以确认方法的作用。

巧合的是,这个问题的一个变体出现在 谜题者归来:Schlock 和 Awe (TS-5186),Josh Bloch 和 Neal Gafter 的 2009 年 JavaOne 技术会议演示。这是总结幻灯片:

道德

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

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

相关问题


关于自动拆箱

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

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

这里引用了《Effective Java》第 2 版第 49 条:“优先选择原始类型而不是装箱原始类型”:

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

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

相关问题

The Big Picture

There are two issues at play here:

  • Integer getInteger(String) doesn't do what you think it does
    • It returns null in this case
  • the assignment from Integer to int causes auto-unboxing
    • Since the Integer is null, NullPointerException is thrown

To parse (String) "123" to (int) 123, you can use e.g. int Integer.parseInt(String).

References

Integer API references


On Integer.getInteger

Here's what the documentation have to say about what this method does:

public static Integer getInteger(String nm): Determines the integer value of the system property with the specified name. If there is no property with the specified name, if the specified name is empty or null, or if the property does not have the correct numeric format, then null is returned.

In other words, this method has nothing to do with parsing a String to an int/Integer value, but rather, it has to do with System.getProperty method.

Admittedly this can be quite a surprise. It's unfortunate that the library has surprises like this, but it does teach you a valuable lesson: always look up the documentation to confirm what a method does.

Coincindentally, a variation of this problem was featured in Return of the Puzzlers: Schlock and Awe (TS-5186), Josh Bloch and Neal Gafter's 2009 JavaOne Technical Session presentation. Here's the concluding slide:

The Moral

  • Strange and terrible methods lurk in libraries
    • Some have innocuous sounding names
  • If your code misbehaves
    • Make sure you're calling the right methods
    • Read the library documentation
  • For API designers
    • Don't violate the principle of least astonishment
    • Don't violate the abstraction hierarchy
    • Don't use similar names for wildly different behaviors

For completeness, there are also these methods that are analogous to Integer.getInteger:

Related questions


On autounboxing

The other issue, of course, is how the NullPointerException gets thrown. To focus on this issue, we can simplify the snippet as follows:

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

Here's a quote from Effective Java 2nd Edition, Item 49: Prefer primitive types to boxed primitives:

In summary, use primitives in preference to boxed primitive whenever you have the choice. Primitive types are simpler and faster. If you must use boxed primitives, be careful! Autoboxing reduces the verbosity, but not the danger, of using boxed primitives. When your program compares two boxed primitives with the == operator, it does an identity comparison, which is almost certainly not what you want. When your program does mixed-type computations involving boxed and unboxed primitives, it does unboxing, and when your program does unboxing, it can throw NullPointerException. Finally, when your program boxes primitive values, it can result in costly and unnecessary object creations.

There are places where you have no choice but to use boxed primitives, e.g. generics, but otherwise you should seriously consider if a decision to use boxed primitives is justified.

Related questions

凉月流沐 2024-09-14 02:39:55

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

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

你想要这个:

Integer.parseInt("123")

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

getInteger 'Determines the integer value of the system property with the specified name.'

You want this:

Integer.parseInt("123")
雪若未夕 2024-09-14 02:39:55

请检查该方法的文档 getInteger()
在此方法中,String 参数是一个系统属性,用于确定具有指定名称的系统属性的整数值。正如此处所述,“123”不是任何系统属性的名称。
如果您想将此字符串转换为 int,请使用该方法:
int num = Integer.parseInt("123")

Please check documentation of the method getInteger().
In this method, the String parameter is a system property that determines the integer value of the system property with the specified name. "123" is not the name of any system property, as discussed here.
If you want to convert this String to int, then use the method as
int num = Integer.parseInt("123").

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文