Friday, 20 September 2013

Tricky instanceof operator

Let's start with a little puzzle.
Object obj = ...
System.out.println(obj instanceof Object);
How do you initialize the obj in order to print "false"?
Well, aren't all possible Java objects instances of Object? To answer this question one must understand how instanceof operator works. The answer is that it would print "true" for any Object. The only way to make it false is not to give it an object, give it a null reference.
The tricky bit about instanceof operator can be that if object on the left side is null, the condition evaluates to false. Therefore there is no need for null check after a class cast as in the following example.
public boolean equals(Object o) {
  if (o instanceof MyClass) {
    MyClass mc = (MyClass) o;
    if (mc == null) // never null
      return false;
    else
      return ... // compare members of mc
  }
  return false;
}
This can be simplified as shown in the following code snippet
public boolean equals(Object o) {
  if (o instanceof MyClass) {
    MyClass mc = (MyClass) o;
    return ... // compare members of mc
  }
  return false;
}
So the moral if this excercise is that instanceof operator works as you would expect with objects, and returns false when given a null.
And remember that equals() method is probably the only reasonable place for instanceof operator. If you do it elsewhere and use it to create an alternative flow (e.g. if-else, switch) it is a bad smell and should be replaced with polymorphism. 
BTW the previous example was not a very nice example of how to implement equals method, so do not copy it ;-) Usually we would do something like this
public boolean equals(Object o) {
  if (o == null) return false;
  if (o == this) return true;
  if (!(o instanceof MyClass)) return false;
  MyClass mc = (MyClass) o;
  return ... // compare members of mc
}

No comments: