How to determine an object's class?

727,074

Solution 1

if (obj instanceof C) {
//your code
}

Solution 2

Use Object.getClass. It returns the runtime type of the object.

Solution 3

Multiple right answers were presented, but there are still more methods: Class.isAssignableFrom() and simply attempting to cast the object (which might throw a ClassCastException).

Possible ways summarized

Let's summarize the possible ways to test if an object obj is an instance of type C:

// Method #1
if (obj instanceof C)
    ;

// Method #2
if (C.class.isInstance(obj))
    ;

// Method #3
if (C.class.isAssignableFrom(obj.getClass()))
    ;

// Method #4
try {
    C c = (C) obj;
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

// Method #5
try {
    C c = C.class.cast(obj);
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

Differences in null handling

There is a difference in null handling though:

  • In the first 2 methods expressions evaluate to false if obj is null (null is not instance of anything).
  • The 3rd method would throw a NullPointerException obviously.
  • The 4th and 5th methods on the contrary accept null because null can be cast to any type!

To remember: null is not an instance of any type but it can be cast to any type.

Notes

  • Class.getName() should not be used to perform an "is-instance-of" test becase if the object is not of type C but a subclass of it, it may have a completely different name and package (therefore class names will obviously not match) but it is still of type C.
  • For the same inheritance reason Class.isAssignableFrom() is not symmetric:
    obj.getClass().isAssignableFrom(C.class) would return false if the type of obj is a subclass of C.

Solution 4

You can use:

Object instance = new SomeClass();
instance.getClass().getName(); //will return the name (as String) (== "SomeClass")
instance.getClass(); //will return the SomeClass' Class object

HTH. But I think most of the time it is no good practice to use that for control flow or something similar...

Solution 5

Any use of any of the methods suggested is considered a code smell which is based in a bad OO design.

If your design is good, you should not find yourself needing to use getClass() or instanceof.

Any of the suggested methods will do, but just something to keep in mind, design-wise.

Share:
727,074
Syed Sami Zia
Author by

Syed Sami Zia

.

Updated on July 08, 2022

Comments

  • Syed Sami Zia
    Syed Sami Zia almost 2 years

    If class B and class C extend class A and I have an object of type B or C, how can I determine of which type it is an instance?

  • Bill the Lizard
    Bill the Lizard over 15 years
    Yeah, probably 99% of the uses of getClass and instanceof can be avoided with polymorphic method calls.
  • Syed Sami Zia
    Syed Sami Zia over 15 years
    i am in agreement. in this case i'm working with objects generated from xml following a poorly designed schema which i do not have ownership of.
  • Yuval Adam
    Yuval Adam over 15 years
    That's generally the case in these situations, legacy code, bad design not in your ownership, etc...
  • StackOverflowed
    StackOverflowed about 12 years
    Also, there are times when you need to ensure that the object is of the same class you're comparing with; for instance I like to override Object's equals method when I create my own class. I always verify the object coming in is of the same class.
  • Dzhuneyt
    Dzhuneyt over 11 years
    It is useful to note the reverse check or how to check if an Object is NOT an instance of a class: if(!(obj instanceof C))
  • Adrián Pérez
    Adrián Pérez almost 11 years
    Also, I would say telling people something is bad without explaining exactly why or giving a reference to a paper, book, or any other resource where the issue is explained is considered not constructive. Therefore and knowing that I am in StackOverflow, I don't know why people have upvoted this answer so much. Something is changing here...
  • tiboo
    tiboo over 10 years
    some tasks like serializing, getting type maybe the simplest way?
  • ElfsЯUs
    ElfsЯUs over 10 years
    There are other cases especially hen discussing DI or producer frameworks where knowing the class types is necessary for binding.
  • Bhavesh Agarwal
    Bhavesh Agarwal about 10 years
    I believe getClass() method is the answer to the original question. In this case (obj instanceof A) would also give "true" output but the intent is to find the runtime class of the object in picture. If Parent1 is extended by Child1 and Child2, try the following code Child1 child1 = new Child1(); Parent1 parentChild = new Child2(); Child2 child2 = new Child2(); (child1 instanceof Parent1); (child1 instanceof Child1); (parentChild instanceof Child2); (parentChild instanceof Parent1); (parentChild instanceof Child1); code , it may clear the intent of instanceof.
  • JohnMerlino
    JohnMerlino almost 10 years
    Definitely an alternative to building an interface
  • olyv
    olyv over 9 years
    What if I have two classes implementing single interface? How do I distinct exact class of the object?
  • Kelsin
    Kelsin almost 9 years
    This is a really great summary of many of the pitfalls in the different methods. Thanks for such a complete write up!
  • x6iae
    x6iae over 8 years
    this is correct. using only obj.getClass() will return the className, prefixex by the word class
  • MBH
    MBH over 8 years
    I used it to create generic logger, So i sent object to the logger, and it logs depending on the class name of the object, rather than giving log tag or log string everytime. thank you
  • MBH
    MBH over 8 years
    I agree with @AdriánPérez Cuz In my case, using getClass for an object saved my API from overhead of giving the name by hand everytime developer initializes the API class. Here to be OO and save the redundant repetition of code, i needed to use object.getClass().getSimpleName() , this is one case, i think there are many more where developer needs instanceof to make function generic and follow OO principles...
  • andand
    andand over 8 years
    In theory there's no difference between theory and practice; in practice there is (Snepscheut). OO theory is fine, but when confronted with the real world things get ugly.
  • alexbt
    alexbt almost 8 years
    One thing though, it does not work if obj is null. The solution would then be ParentInterface.class.isAssignableFrom(Child.class)
  • shareef
    shareef about 7 years
    request.getClass().getName(); prints all package ! along with class name
  • AA_PV
    AA_PV about 7 years
    This is actually how you determine an object's class
  • JMess
    JMess almost 6 years
    Imagine case where you have B, C, D, E, etc. Solution becomes very verbose. Pattern matching is much better but is still in proposal state.
  • Gaurav
    Gaurav over 5 years
    flawless answer @Bill
  • KrystosTheOverlord
    KrystosTheOverlord about 5 years
    I know I'm a bit late here, but I see your point on how it shouldn't be necessary, though recently I had run into a situation that actually needed it, and that situation was in the override of Object's equals method. I needed to create a special case within HashMap that agreed with equality, but the usual equals method did not work. There may have been a better method for doing so, but the instanceof function really helped
  • eicksl
    eicksl over 4 years
    Not sure why this is not the most popular answer
  • JOE
    JOE about 3 years
    I can't agree with you. If you want to override an equals function: @Override public boolean equals(Object obj){}, you must check the class type. Activity, it is a bad OO design if you don't use getClass()/instanceof.
  • Holger
    Holger over 2 years
    Using generics here, adds no value. Change the method declaration to public void print(Object data) and it will still work exactly the same.