java.sql.timestamp vs java.util.date

I came across an interesting problem when a co-worker brought me a stack trace for review.

We are upgrading our application servers to run on Java 5. (Was running Java 1.4). Her code was unchanged, but suddenly started throwing a ClassCastException when comparing two Date objects.

It turns out that one of the Date objects was actually a java.sql.Timestamp (which extends java.util.Date) and the other was a java.util.Date.

In Java 1.4, if you call Timestamp.compareTo(Date), you’ll always get a not equals value (non-zero). This is because Timestamp implements the compareTo(Timestamp) method and inherits compareTo(Object). There is no compareTo(Date) method, so the call fails over to the Object implementation.

In Java 5, there is a Timestamp.compareTo(Date) method. Javadocs specify that the Date parameter must actually be a Timestamp.

As a result, code that ran in Java 1.4 (though errantly) now throws a ClassCastException. It is maddening to find as there is no indication of this at compile time (both are Date objects after all).

Here’s another explanation of the problem.
http://mattfleming.com/node/141

Moral of the story:
Date.compareTo(Timestamp) is OK because Timestamp extends Date
Timestamp.compareTo(Date) is NOT OK.