How to check if a subclass is an instance of a class at runtime?
Solution 1
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)
Solution 2
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).
Solution 3
Maybe I'm missing something, but wouldn't this suffice:
if (view instanceof B) {
// this view is an instance of B
}
Solution 4
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
.
Solution 5
It's the other way around: B.class.isInstance(view)
Related videos on Youtube
iamamused
Updated on July 05, 2022Comments
-
iamamused almost 2 years
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 anA
object it doesn't evaluate to an "instance ofB
". Is there a way to doisSubclassOf
or something?-
ishmeister over 14 yearsFrom 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.
-
iamamused over 14 yearsIt'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 :)
-
Timofey about 12 yearsif viewList array is null, then your program crashes, even check in while does not help.
-
kiwicomb123 over 7 yearsClass invariant assertions is a case where this is done. (As iamamused said)
-
joseluisbz about 5 yearsThis is my Answer stackoverflow.com/a/55860069/811293
-
-
Ben Clayton over 11 years+1 for if (view instanceof B). Simple and works.
-
ArtOfWarfare over 11 yearsI'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.
-
Qix - MONICA WAS MISTREATED over 11 yearsNote that
instanceof
won't work for generics due to erasure. -
Hardcoded about 11 years@Qix Thanks for the info. Erasures are a pain in more than one body part, but working without Generics is worse.
-
Qix - MONICA WAS MISTREATED about 11 yearsTo be honest I don't even view Java's generics as true generics; Java's generics are simply syntactic sugar for type safety (or, more importantly, enforcement). They are purely compile time and I think most people coming from C++ and subsequently templates will have a hard time grasping the concept of erasure.
-
Hardcoded about 11 yearsThe method is badly named and documented. It won't help with the problem, since neither A nor B have any generics.
-
Hardcoded over 9 yearsDon'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){ }
-
David over 4 yearsnot recommendable to test something using try ... catch