Friday, November 12, 2010

Java Grievances part 2

At some point the concept of a foreach construct was implemented in Java. This is a really nice construct that allows one to change code like this:

int sum = 0;
Enumeration<Integer> it = some_list.getEnumerator();
    sum += it.nextElement();
into code like this:

int sum = 0;
for(Integer i : some_list)
    sum += i;

This is quite nice, unfortunately, it is an addon so many Java libraries has no support for this. Even some of the more prominent libraries such as org.xml.sax and java.util.Hashtable have no support for the enumeration feature, even if they are obvious candidates. Nice try, but does not really give any punch as it is mostly not usable.

This is some of the same problems that occurs when using generics, which is not supported by the Java bytecode, so all the generic types are removed during compilation (called type erasure). The benefit of this is that code can use generics internally but still expose a non-generic interface externally. If this was the programmers intention, it could be done anyway, but now the choice is not there. The reason for this is obviously compatibility, but the implications are that the libraries are forced to expose a legacy interface. The really nice way to do this would be to set a compile switch that toggles either generic output, or type erasure. Again, nice try but does not really give anything.

The other problem is in the design philosophy where Java opts for having a single get() method which then takes an enumeration value as input. The notable example is the Calendar.get function which takes a number of integer values as input and returns different things. This approach means that the programmer has to look up what values are allowed, or guess the naming convention used for this particular method. It also means that the get method must validate all input to ensure that the user supplied a valid value.

A much better approach would be to simply make different functions, as that is what it really is. Example:
Calendar today = Calendar().getInstance();
int day = today.get(Calendar.DAY_OF_WEEK);
int month = today.get(Calendar.MONTH) + 1;

int day = today.getDayOfWeek();
int month = today.getMonth() + 1;

That way the documentation is less required, there are no run-time errors as the programmer cannot supply an invalid value, a win-win. Well, one can dream :)

No comments: