Alex Rivera | Logout

Why cast after an instanceOf?

Asked 2010-11-15T16:12:40.693
55

In the example below (from my coursepack), we want to give to the Square instance c1 the reference of some other object p1, but only if those 2 are of compatible types.

if (p1 instanceof Square) {c1 = (Square) p1;}

What I don't understand here is that we first check that p1 is indeed a Square, and then we still cast it. If it's a Square, why cast?

I suspect the answer lies in the distinction between apparent and actual types, but I'm confused nonetheless...

Edit:
How would the compiler deal with:

if (p1 instanceof Square) {c1 = p1;}

Edit2:
Is the issue that instanceof checks for the actual type rather than the apparent type? And then that the cast changes the apparent type?

Edit
Report

3 Answers

19

Keep in mind, you could always assign an instance of Square to a type higher up the inheritance chain. You may then want to cast the less specific type to the more specific type, in which case you need to be sure that your cast is valid:

Object p1 = new Square();
Square c1;

if(p1 instanceof Square)
    c1 = (Square) p1;
answered 2010-11-15T16:15:44.020
1

The test is done to prevent from ClassCastExceptions at runtime:

Square c1 = null;
if (p1 instanceof Square) {
   c1 = (Square) p1;
} else {
   // we have a p1 that is not a subclass of Square
}

If you're absolutly positive that p1 is a Square, then you don't have to test. But leave this to private methods...

answered 2010-11-15T16:17:44.703
1

Not to be obnoxious, but you have to tell the compiler what you want to do because the alternative would be for it to guess what you're trying to do. Sure, you might think, "If I'm checking the type of an object, OBVIOUSLY that must mean that I want to cast it to that type." But who says? Maybe that's what you're up to and maybe it isn't.

Sure, in a simple case like

if (x instanceof Integer)
{
  Integer ix=(Integer) x;
  ...

My intent is pretty obvious. Or is it? Maybe what I really want is:

if (x instanceof Integer || x instanceof Double)
{
  Number n=(Number) x;
... work with n ...

Or what if I wrote:

if (x instanceof Integer || x instanceof String)

What would you expect the compiler to do next? What type should it assume for x?

RE the comments that instanceof is obsolete or otherwise a bad idea: It can certainly be mis-used. I recently worked on a program where the original author created six classes that all turned out to be pages and pages long, but identical to each other, and the only apparent reason for having them was so he could say "x instanceof classA" versus "x instanceof classB", etc. That is, he used the class as a type flag. It would have been better to just have one class and add an enum for the various types. But there are also plenty of very good uses. Perhaps the most obvious is something like:

public MyClass
{
  int foo;
  String bar;
  public boolean equals(Object othat)
  {
    if (!(othat instanceof MyClass))
      return false;
    MyClass that=(MyClass) othat;
    return this.foo==that.foo && this.bar.equals(that.bar); 
  }
  ... etc ...
}

How would you do that without using instanceof? You could make the parameter be of type MyClass instead of Object. But then there's be no way to even call it with a generic Object, which could be highly desirable in many cases. Indeed, maybe I w

answered 2010-11-15T17:59:49.647

Your Answer