81

In an android app test suite I have a class like this where B is a view:

public class A extends B {
... etc...
}

now I have a list of view objects which may contain A objects but in this case I only care if they're subclasses or "instances of" B. I'd like to do something like:

ArrayList<View> viewList = getViews();
Iterator<View> iterator = viewList.iterator();
while (iterator.hasNext() && viewList != null) {
    View view = iterator.next();
    if (view.getClass().isInstance(B.class)) {
        // this is an instance of B
    }
}

The problem is that when the if encounters an A object it doesn't evaluate to an "instance of B". Is there a way to do isSubclassOf or something?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
iamamused
  • 2,720
  • 3
  • 25
  • 17
  • 1
    if viewList array is null, then your program crashes, even check in while does not help. – Timofey Apr 27 '12 at 09:44
  • 3
    From Effective C++, by Scott Meyers : "Anytime you find yourself writing code of the form "if the object is of type T1, then do something, but if it's of type T2, then do something else," slap yourself. Could you not use an overridden method instead? Or perhaps something like the visitor pattern. – ishmeister Mar 10 '10 at 11:07
  • 1
    It's for a test case so the code is not actually in the production app, it's to test to make sure things are using the right classes :) – iamamused Mar 11 '10 at 05:01
  • Class invariant assertions is a case where this is done. (As iamamused said) – kiwicomb123 Mar 23 '17 at 01:40
  • This is my Answer https://stackoverflow.com/a/55860069/811293 – joseluisbz Apr 26 '19 at 02:48

7 Answers7

174

You have to read the API carefully for this methods. Sometimes you can get confused very easily.

It is either:

if (B.class.isInstance(view))

API says: Determines if the specified Object (the parameter) is assignment-compatible with the object represented by this Class (The class object you are calling the method at)

or:

if (B.class.isAssignableFrom(view.getClass()))

API says: Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter

or (without reflection and the recommended one):

if (view instanceof B)
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
Hardcoded
  • 6,476
  • 2
  • 22
  • 20
25
if(view instanceof B)

This will return true if view is an instance of B or the subclass A (or any subclass of B for that matter).

Kris
  • 14,426
  • 7
  • 55
  • 65
  • 3
    I'd like to mention that B must be imported in the current .java file for this to work. Eclipse will flag the line as having an error but offer no helpful solutions otherwise (wasted nearly an hour trying different syntax before realizing I just hadn't imported the class file.) For anyone wondering, the correct syntax is ((instance name) instanceof (Class name)). The word class doesn't show up anywhere in it. – ArtOfWarfare Nov 15 '12 at 19:32
10

Maybe I'm missing something, but wouldn't this suffice:

if (view instanceof B) {
    // this view is an instance of B
}
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
7

Class.isAssignableFrom() - works for interfaces as well. If you don't want that, you'll have to call getSuperclass() and test until you reach Object.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
2

It's the other way around: B.class.isInstance(view)

nanda
  • 24,458
  • 13
  • 71
  • 90
1

If there is polymorphism such as checking SQLRecoverableException vs SQLException, it can be done like that.

try {
    // sth may throw exception
    ....
} catch (Exception e) {
    if(SQLException.class.isAssignableFrom(e.getCause().getClass()))
    {
        // do sth
        System.out.println("SQLException occurs!");
    }
}

Simply say,

ChildClass child= new ChildClass();
if(ParentClass.class.isAssignableFrom(child.getClass()))
{
    // do sth
    ...
}
vientoho
  • 39
  • 3
  • 3
    Don't do something like catching Exception and checking for the class of the exception, if you don't have a REALLY good reason for it. do instead: `} catch (SQLException e) { } catch (Exception e){ }` – Hardcoded Dec 15 '14 at 15:04
  • not recommendable to test something using try ... catch – Dave Feb 10 '20 at 15:35
-1

I've never actually used this, but try view.getClass().getGenericSuperclass()

chama
  • 5,973
  • 14
  • 61
  • 77
  • 1
    The method is badly named and documented. It won't help with the problem, since neither A nor B have any generics. – Hardcoded Jun 24 '13 at 14:46