Why instanceof is not so hot

person Bijeshfolder_openJavalocal_offeraccess_time October 1, 2008

Everyone knows the ubiquitous instanceof operator especially when we drill into our minds that instanceof is not a method, it is an operator. :-) You would’ve found it useful in many situations especially when you need to do a bit of refactoring or reflection. This is one operator any programmer ought to be careful about. Unfortunately, you find it strewn around the place all the time.  When used in the wrong place it easily becomes a bug. 

What’s wrong with the instanceof operator, you ask? Nothing major, except that by its definition instanceof evaluates to true for the parents of a given class as well. I agree it was meant to be so but that is what makes it tricky to use as well. Let me give you an example. Say you have two methods

1. writeToFile – takes an Object param and based on its type it writes out the object into a file as a String. Yep, some kind of serialization. One of the object types tested for is java.util.Date. For Date, toString() uses the format “EEE MMM dd HH:mm:ss z yyyy”

public void writeToFile(OutputStream fileStream, Object o)
{
   ...
   else if (data instanceof Date)
   {
        fileStream.write("");
        fileStream.write(date.toString());
        fileStream.write("");
   }
   .....
}

2. readFromFile – reads a file and – you guessed it –  spews out an Object. Something like this therefore.

public Object readFromFile(InputStream fileStream)
{
   Object retObj = null;
   ...
   else if (tag.equals(""))
   {
        String dateString = fileStream.readValue();
        SimpleDateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
        retObj  = df.parse(dateString);
   }
   .....
   return retObj;
}

Alright, now this would perfectly well if the obj passed into writeToFile is a java.util.Date. What happens if the argument is a java.sql.Timestamp. writeToFile would still succeed because Timestamp is a child class of java.util.Date but when someone tries to read the object back from the file, you will hit a parse error. Why?? Look carefully, I have allowed the default pattern by using toString to encode the Date. In the case of java.sql.Timestamp, this default pattern is the JDBC escape pattern and quite different from “EEE MMM dd HH:mm:ss z yyyy”.

Ofcourse, you can argue that instead of using toString(), the right way would have been to use an SDF to format it. What happens to the nanoseconds that Timestamp supports then? SDF does not support nanosecs!

This is one place where there is a need to identify a Timestamp correctly. This could’ve been done by comparing the Class of the objects instead of or in addition to the instanceof operator. That’s just one example. There can be many other situations like this. Beware of class hierarchies and beware of instanceof.

Comment

  1. Nice catch for the use of instanceOf operator.

    instanceOf is used in equals() operation as well. So if you are creating your own classes that need to be used in collections like HashSet, then you could run in these kind of problems as well if you allow your classes to be extended.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>