Why Timestamp cannot be used in place of Date in Java?

One of the tricky question from Java Interview is, "Can we pass a Timestamp instance to a method expecting java.util.Date?", it's a tricky question because the answer is both Yes and No. You can, of course, pass a Timestamp object to a method with the argument as Date because first, Timestamp is a subclass of java.util.Date and second it contains both date and time values which are missing in either java.sql.Date and java.sql.Time. So there is more reason to pass a Timestamp value to Date but you should not be doing that. Why? because Timestamp is not exactly Date. It's a composite type of java.util.Date and an additional nanosecond value which is fitted there to confirm database DATETIME data type, which supports nanosecond precision. If you look at the implementation of java.sql.Timestamp class, you will find that the long value supplied by Date is stored separately then this nanosecond value.

You cannot even compare Date to Timestamp class in Java. The Timestamp.equals(Object) method returns false when you pass an instance of java.util.Date because the nanos component of a date is unknown. As a result, the Timestamp.equals(Object) method is not symmetric with respect to the java.util.Date.equals(Object) method. Also, the hashCode method uses the underlying java.util.Date implementation and therefore does not include nanos in its computation. See Core Java Volume 2 - Advanced Features by Cay S. Horstmann to learn more about different date and time classes of SQL packages.




To understand the difference between Timestamp and Date better, let me show an example of comparing Date and Timestamp object in Java:

import java.sql.Timestamp;
import java.util.Date;

/*
 * Java Program to compare Date and Timestamp in JDBC
 */

public class TimeStampVsDate {

  public static void main(String[] args) {

    Date date = new Date();
    Timestamp timestamp = new Timestamp(date.getTime());

    if (date.equals(timestamp)) {
      System.out
          .println("Both Date and Timestamp are equal, when you compare using Date.equals() method");
    }

    if (!timestamp.equals(date)) {
      System.out
          .println("But, they are not equal when you compare them using Timestamp.equals() method");
    }

  }
}

Output
Both Date and Timestamp are equal, when you compare using Date.equals() method
But, they are not equal when you compare them using Timestamp.equals() method

So, you can see they break the symmetry property of equals() method which says if a.equals(b) is true then b.equals(a) should also be true.

For those who needs a little bit of revision about which Java type mapped to which SQL type in database, here is a nice slide about Java to SQL type mapping:

Why Timestamp cannot be used as Date in Java JDBC


So, even though both Date and Timestamp contains date and time value and their respective getMonth(), getHours() method doesn't throw IllegalArgumentException, you should not be using Timestamp in place of java.util.Date due to the differences mentioned above. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance, which is not a good design but sometimes finds its way through even a well designed API like JDK or JDBC.


Other JDBC Date and Time articles you may like
  • Difference between java.util.Date and java.sql.Date in JDBC? (answer)
  • Difference between java.sql.Time, java.sql.Timestamp, and java.sql.Date in JDBC? (answer)
  • How to convert java.util.Date to java.sql.Date in JDBC? (example)
  • How to convert java.sql.Date to java.util.Date in JDBC? (example)
  • How to convert java.util.Date to java.sql.Timestamp in JDBC? (example)
  • Why is String class made final in Java? (answer)
  • Why Hibernate Entity class should not be final in Java? (answer)

References
Java SE 7 documentation of Timestamp
Java SE 8 documentation of Timestamp



No comments :

Post a Comment