Wednesday, July 8, 2009

Java Brainteasers

I had lunch with a few colleagues yesterday and we started talking about obscure stuff. Among other things we talked about:
  • the initial default size of a hashmap, which is a power of 2 (16) in HashMap but a prime number (11) in Hashtable in java 1.6 (possible explanation, see the 'Tip' section)
  • the strictfp keyword, which can be used to ensure that floating point numbers behave the same on all hardware.
  • the volatile keyword, which seems to have a slightly different behavior since 1.5. I did not find anything from Sun about this, but I found some references indicating that something might actually have changed... Basically it seems that writing to a volatile variable synchronizes all cached copies of variables with the main memory, not just the volatile variable itself. I must admit this one was totally new to me.
Anyway that reminded me about Java Puzzlers, a book about obscure features of Java in the form of puzzles. I decided to go through the book again to see if I would gain anything. Although many puzzles show how things can go hairy while using really bad code, a few bits of knowledge can always be useful. Here is a few of the things I learned (or re-learned) while skimming through the book:

Weird behavior of Math.abs
The absolute value is not always positive!
Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE

Unicode considered evil (at least problematic in comments)
Unicode characters in comments can cause problems. Consider the following comment:
/*
Test files are located in \utest\samples
*/

The file will not compile because the java compiler tries to convert \utest to a Unicode character (I saw this in a real project once)

Escape regex
I learned that Pattern.quote() can be used to automatically escape a literal string as a regular expression.
System.out.println(Pattern.quote(".")) will print \Q.\E

This method was added in Java 5.

Recursive array printing
I also learned about the Array.deepToString() method, which can output the content of multi-dimensional arrays. This method was also added in 1.5.
int[][] array = new int[][] {{1, 2, 3}, {4, 5}};

System.out.println(array); => [[I@1ad086a
System.out.println(Arrays.deepToString(array)); => [[1, 2, 3], [4, 5]]

Ternary operator madness
And finally the behavior of the ternary operator (? :) was changed in 1.5. Consider the following statement:
boolean b = true; // or false, doesn't matter
List list = b ? new ArrayList() : new Vector();


In 1.5, the code compiles fine.
In 1.4, I get an error 'Incompatible conditional operand types ArrayList and Vector'.
Before 1.5, both values returned by the ternary operator must have a shared ancestor other than Object. In 1.5 the requirement was relaxed - any common ancestor is fine, and since all classes inherit from Object you can return two completely unrelated classes.

Now why would you want to do something like this?
Object o = b ? new ArrayList() : new JButton();

Don't ask me, I'm just the messenger...

No comments:

Post a Comment