开发者

Why does int num = Integer.getInteger("123") throw NullPointerException?

The following code throws NullPointerException:

int num = Int开发者_运维问答eger.getInteger("123");

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

What's happening?


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

  • Java Language Guide/Autoboxing

Integer API references

  • static int parseInt(String)
  • static Integer getInteger(String)

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:

  • Boolean.getBoolean(String)
  • Long.getLong(String)

Related questions

  • Most Astonishing Violation of the Principle of Least Astonishment
  • Most awkward/misleading method in Java Base API ?

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

  • What is the difference between an int and an Integer in Java/C#?
  • Why does autoboxing in Java allow me to have 3 possible values for a boolean?
  • Is it guaranteed that new Integer(i) == i in Java? (YES!!!)
  • When comparing two Integers in Java does auto-unboxing occur? (NO!!!)
  • Java noob: generics over objects only? (yes, unfortunately)


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")


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").

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜