views:

173

answers:

5

Say I have 3 classes like so:

class A {}
class B extends A {}
class C extends A {}

Would it then be possible to determine whether a particular object was an instance of A, B, or C?

I thought that something like this might work:

if (myObject.getClass().isInstance(B.class)) {
    // do something for B
} else (myObject.getClass().isInstance(C.class)) {
    // do something for C
} else {
    // do something for A
}

but after reading a little I think it would always evaluate as B since it's just testing if a cast would work and there's no substantial differences between them.

+6  A: 

Do this:

if (myObject instanceof B) {
    // do something for B
} else (myObject instanceof C) {
    // do something for C
} else {
    // do something for A
}
NawaMan
Thanks for the quick reply... exactly what I was looking for.
fiXedd
+9  A: 

The simpler and faster code is:

if (myObject instanceof B) {
} else if (myObject instanceof C) {
} else if (myObject instanceof A) {
}

Note that the order is important: you have to have the test for A last, as that will succeed for instances of B and C as well.

However, your original code would nearly work. Class.isInstance checks whether the value really is an instance of the given class or any superclass. So if myObject is an instance of C, then B.class.isInstance(myObject) will return false. All you've got wrong is that you're calling getClass() on myObject unnecessarily, instead of using B.class etc.

This is the approach you would take if you didn't know which classes you were interested in at compile time - the instanceof operator only works when you can specify the type statically in code.

Now if you want to find out whether myObject is an instance of exactly B (and not a subclass) then just use:

if (myObject.getClass() == B.class)

(This will blow up if myObject is a null reference, of course.)

Jon Skeet
Answered in typical stack-overfl...I mean, Skeet-overkill style. :D
Epaga
A: 

There is the instanceof operator that does what you want, as others have answered.

But beware that if you need something like this, it's a sign that there might be a flaw in the design of your program. The better, more object oriented way to do this is by using polymorphism: put a method in the superclass A, override that method in B and C, and call the method on myObject (which should have type A):

A myObject = ...;  // wherever you get this from

// Override someMethod in class B and C to do the things that are
// specific to those classes
myObject.someMethod();

instanceof is ugly and should be avoided as much as possible, just like casting is ugly, potentially unsafe and should be avoided.

Jesper
+1  A: 

You also might want to look at the double dispatch idiom which is an OO way of changing behaviour based on the type of an argument in languages which don't support multi-methods.

Pete Kirkham
A: 

you could do this

if (myObject.getClass() == B.class) {
    // do something for B (not subclasses of b!!!)
} else if(myObject.getClass() == C.class) {
    // do something for C (not subclasses of c!!!)
} else if(myobject.getClass() == A.class) {
    // do something for A (not subclasses of A!!)
} else if(myobjects instanceof A){
   //all other subclasses of A
}
KitsuneYMG