Thursday, January 17, 2008

Java Integer.decode broken

If you're aware of two's compliment representation of integers, you can probably guess the output of the following line of Java:

System.out.println(Integer.toHexString(-1));

Sure enough, you get this:

ffffffff

Knowing that, what do you think the result of this line might be?

System.out.println(Integer.decode("0xffffffff"));

Would you believe NumberFormatException: For input string: "ffffffff"? The reason is that decode works on signed values. Ugly with a capital Ug. Decode works as expected on hexadecimal values in which the most significant bit is clear. But here, that high bit is set. The decode function expects a negative hex value where ever you'd use a negative decimal value.

Now, what would be a proper punishment for the kind of protohuman homunculus who would use a sign with a hexadecimal number? Fifty lashes with a wet noodle for the addled mind that thought this was a good idea:

Integer.toHexString(Integer.decode("-0x1"));
ffffffff

Most sane programmers find this highly annoying. There's a bug dated in 1999, (and several dupes) in the Java bug database for this, and its counterpart bug in Long. What an embarrassment.

One work-around (for integers) is to use a Long when you expect a hex number with the sign bit set.

int thisIsTotallyWeak = Long.decode("0xffffffff").intValue();