Monday, December 19, 2011

An example of Java being broken-by-design

Java complaint: java.sql.Timestamp is based upon java.util.Date, so you can pass it to functions expecting a java.util.Date. The difference is that java.util.Date specifies time is millisecond-precise and java.sql.Timestamp specifies time is nanosecond-precise. They can both be assigned a value using using a millisecond-accurate function with the same name. However, if you compare a Date and a Timestamp initialized to the same millisecond-accurate time, they are never equal.

This means that while there is fancy object-oriented code-reuse arm-waving, if you actually try to use these classes in a generic manner things fail mysteriously. This is fundamental breakage in the design. First they "enforce type-safety" then if you actually rely upon type-safey you get bit in the ass.

This is documented (from http://docs.oracle.com/javase/7/docs/api/java/sql/Timestamp.html):
Due to the differences between the Timestamp class and the java.util.Date class mentioned above, it is recommended that code not view Timestamp values generically as an instance of java.util.Date. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance.
This gets me in a lather. Clearly being a child of java.util.Date means nothing.

What they should have done was have a Date-like interface specifying the getTime()/setTime(long) functions and defined that they accepted time in milliseconds and their epoch. Then we could use any getTime()/setTime() related function the same without caring about the advanced features it possessed.

As it is there are too many different ways to specify dates and they're all incompatible. It's almost easier to pass time around in milliseconds and convert to the desired type as-needed.

No comments: