Follow by Email

Friday, April 11, 2008

Integer.getInteger. Are you kidding me?

Photos and diary are on haitus. Now a little technology.

I just discovered a method introduced in Java 5: the method Integer.getInteger(String):

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Integer.html#getInteger(java.lang.String)
Determines the integer value of the system property with the specified name.

The first argument is treated as the name of a system property. System properties are accessible through the System.getProperty(java.lang.String) method. The string value of this property is then interpreted as an integer value and an Integer object representing this value is returned. Details of possible numeric formats can be found with the definition of getProperty.

So let me see if I understand:
  • Integer.valueOf(String) converts a String to a number by assuming the String is a numeric representation. In other words. Integer.valueOf("12345") yields the number 12345.
  • Integer.getInteger(String) converts a String to a number by assuming the String is the name of a system property numeric representation. In other words. Integer.getInteger("12345") is likely to yield null.
Why would anybody consider this a sufficient distinction? How many bugs are people going to create by using getInteger when they meant valueOf and vice versa?

This type of overloading is called near-phrase overloading. I just made that term up right now. It's when people use very similar words to mean different things. Consider two words x and y, their general meanings gm(x) and gm(y), and their meanings in a given context, cm(x) and cm(y). If
distance(gm(x), gm(y))< distance(cm(x), cm(y))
then it's a bad use of x and y! Go find another x and y for their contextual uses. Really, they could have called it getIntegerProperty.

This is the worst case of avoidable ambiguity I've seen in Java; I expect better coming out of them.

Update: it turns out there is something worse: Boolean.getBoolean("true") is usually equal to Boolean.FALSE.

29 comments:

Anonymous said...

I thought that you would just like to know that you just really really helped me.

I'm probably going to start reading your blog now.

Robert Konigsberg said...

I do like to know that kind of stuff! Thanks, Anonymous!

Alejandro said...

Just got bit by this one, really ugly bug...

Leo said...

Thanks, saved me a bit of time.

Anonymous said...

One more thanks, also ran into this. Googling for an Interger-class bug which I suspected led me to your post and will now let me sleep in peace.

Seriously, WTF Sun?

Especially when scrolling through the Method Summaries in the API-Doc it shows up before the valueOf entry and you suspect nothing - at least make "system property" bold, italics and blinking...

Cláudio Esperança said...

Thanks for this... It helped a lot.

Anonymous said...

I always use
Integer.parseInt(String)

It denotes that something is being "parsed", so there's less chance for confusion.

Anonymous said...

In other news, calling Integer.rotateLeft() twice on 6 does not return 9!

Jesus, is it that hard to Read the Fucking Manual?

Anonymous said...

I cannot even begin to describe the level of fail at work here. Not only the ambiguity, but also, HOW IN THE WORLD did anyone seriously think it would be a good to scatter the getters for system properties all over the data type abstractions?

WHY?

Anonymous said...

Actually very few would make this mistake. It fits in and conforms perfectly with their design model (see: Boolean.getBoolean() for example). Perhaps if you do no research or are new to the Java business you could find this really irking, but it's really not a very big flaw.

greenlyblue said...

I think it's funny that you expect better from Java. It's one of the most verbose and ceremonial languages out there and it hasn't moved it's conceptual base forward in like a gazillion years.

Anonymous said...

I agree with greenyblue! I'm not an expert but I've been using a less well-known high level language for over a decade, recently picked up Processing then did a few months messing with Java. It was OK. Recently moved to using a C++ framework for graphics, etc. Compared to Java, I'm writing half the amount of code, it reads much clearer and runs 10 times faster. C++ is hard but Java is a constant WTF-athon.

James said...

I highly suggest that you read Joshua Bloch's "Java Puzzlers" - it covers a lot of the weird Java pitfalls, including this one.

It's saved me from having to debug one the of the weird "why in the world is it doing " bugs a few times, and it's a fun read to see where the Java designers went wrong (as written by one of them, after the fact!)

James said...

@Anonymous - while it's true he shouldn't be calling getInteger, Joshua Bloch (aka the third @author in Integer.java - http://www.docjar.com/html/api/java/lang/Integer$IntegerCache.java.html) has, in a talk, even said that it was a bad decision to have those functions being in the core numeric type libraries - it violates what he calls the "principle of least astonishment" - if you ask a software engineer with no java knowledge what "getInteger(String s)" in class Integer does, more likely than not, you'd expect it transforms the string into an integer. It's the least astonishing thing a method with that name in that class could possibly do - which is exactly what it SHOULD be doing. If it's astonishing to the users that it does , you've named it wrong.

You would NOT, without prior knowledge of the system, expect it to return a system property with that name. A system property is not a feature of the Integer class - rather, the design should have been the other way around. A SystemProperties method called getInteger would be obvious in purpose, even to someone who had never used the system.

So while he "should" know better, the API design is flawed and lends itself to walking into this trap.

Anonymous said...

decode and parseInt are a far more nefarious pair, as decode will behave exactly like parseInt in the majority of cases. Finding that bug was a real PITA, and only by chance I passed in a 0...9 number and got an exception that led me to the erroneous code.

With respect to getInteger vs valueOf I can only say that valueOf is such a repeated pattern that it shouldn't be confused with anything else (a weak justification I know).

Robert said...

Should be:

Integer i = Integer.getSystemProperty(sPropertyName);

or

Integer i = Integer.getSystemPropertyAsInteger(sPropertyName);

Since we're renaming things, maybe "Homonymal Overloading" is a better term for this bad practice than "near-phrase overloading".

Anonymous said...

Why didn't they name the function Integer.valueOfProperty(String)?

Anonymous said...

I love penis

Anonymous said...

similar to parseint?

Anonymous said...

Integer.getProperty()

Calling it Integer.getIntegerProperty() is redundant. The function prototype would be:

int Integer.getInteger()

So renaming it to:

int Integer.getIntegerProperty() is sufficiently overkill. It's not like you would see:

float Integer.getFloatProperty()

That would be insanity, defined.

They made a naming flub, 'tis all.

Anonymous said...

learn how to read

"Returns true if and only if the system property named by the argument exists and is equal to the string "true"."

Anonymous said...

What a pointless article. The documentation says it all. If you don't know what a method does read the documentation. If you use IDE it appears in your intelli-sense. If you are a smart (you don't even have to be that smart) developer you know you should use valueOf or parseInt.

eoin said...

Why would you put a method for getting a system property in a core number type class?

anthonybailey.net said...

"learn how to read" "If you don't know what a method does read the documentation"

These seem to be an argument that names don't really matter much. I strongly disagree.

hdragomir said...

man, I'm so glad I left Java before I could stumble into such ... issues.

Anonymous said...

This is a 1.0 artifact (should really be deprecated).

In those ancient days, system properties were much more commonly used and there was some convenience to this convenience.

There are a number of (in hindsight) glaring design flaws in the old 1.0 APIs (synchronized collections, Properties is-a HashTable, ...)

sfk said...

Wow thanks good to know :P

Anonymous said...

What a pointless article. The documentation says it all. If you don't know what a method does read the documentation.

Yes, you just proved you don't know anything about API design, the principle of least astonishment, code smell, the law of Demeter and programming in general.

Please, do not comment on programming posts again for at least a decade.

Robert Konigsberg said...

@Robert, sorry for the delay. Yes I much prefer your term "Homonymal Overloading."