Java puzzlers

While a great read for toilet visits, unlike Effective Java, I don't consider Java Puzzlers particularly essential material to know as a developer. Not because there isn't anything to learn, but because there are many other pitfalls of the language not mentioned which you are just as likely to encounter before many of the exotic ones mentioned in the book. I recently ran into another one of this kind, which I will now describe.

How low can you go?

Take a look at the following snippet, which is a more flexible version of Math.max() which tries to find the largest Double in an array:

System.out.println( max(0.0, -1.0, -2.0) );

public static double max(double... candidates)

{

assert(candidates.length > 0);

double knownMaxValue = Double.MIN_VALUE;

for(double candidate : candidates)

if(candidate > knownMaxValue)

knownMaxValue = candidate;

return knownMaxValue;

}

What do you think will be printed to System.out? Hint: No, it doesn't have anything to do with autoboxing this time around. Scroll down to read on...

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

Well, I would expect 0.0 to be printed, but instead 4.9E-324 is. That's because Double.MIN_VALUE yields 4.9E-324, the smallest *positive* number. So when we initially assign it to knownMaxValue, thinking it represents the smallest possible value, the net effect is that candidate values less than 0 are not considered at all.

To get the expected behavior, you instead have to initialize with -Double.MAX_VALUE to get the actual smallest number including negative numbers which yields -1.7976931348623157E308.

Justification

You may argue that this is fully specified in the JLS and documented in the JavaDocs, which is true. The JavaDoc for Double states "A constant holding the smallest positive nonzero value of type double". However, I'd consider this to be an extremely easy trap to fall into as it completely defies logic and common sense. Javascript not surprisingly follows the Java definition of Double.MIN_VALUE while more modern languages such as C# defines it the way most people would expect, including negative numbers.

The above puzzler could also have dealt with problems associated with the abnormal signed definition of a java.lang.Byte, or the treacherous scale semantics of a java.math.BigDecimal.equals()or... well you get the idea when I say there are a fair share of puzzlers out there not officially declared so.