608

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?

Lii
  • 11,553
  • 8
  • 64
  • 88
carrier
  • 32,209
  • 23
  • 76
  • 99
  • 14
    @starblue Casting would be the first thing that comes to mind. I doubt the *instanceof* operator would exist if there wasn't any need for it. – arkon Sep 14 '12 at 07:16
  • @b1nary.atr0phy wouldn't it be good to use the isntanceof operator first. If there's a cast to an incompatible type, I believe that will result in a ClassCastException – committedandroider Oct 12 '19 at 17:27

13 Answers13

903
if (obj instanceof C) {
//your code
}
Michael Myers
  • 188,989
  • 46
  • 291
  • 292
IAdapter
  • 62,595
  • 73
  • 179
  • 242
  • 38
    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))` – Dzhuneyt Oct 15 '12 at 08:22
  • 44
    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. – Bhavesh Agarwal May 20 '14 at 11:18
  • Definitely an alternative to building an interface – JohnMerlino Jul 06 '14 at 22:07
  • 3
    What if I have two classes implementing single interface? How do I distinct exact class of the object? – olyv Jan 16 '15 at 14:17
  • 3
    One thing though, it does not work if obj is null. The solution would then be ParentInterface.class.isAssignableFrom(Child.class) – alexbt Jul 13 '16 at 16:24
  • Imagine case where you have B, C, D, E, etc. Solution becomes very verbose. [Pattern matching](https://docs.scala-lang.org/tour/pattern-matching.html) is much better but is [still in proposal state](http://openjdk.java.net/jeps/305). – JMess Aug 21 '18 at 19:53
  • Since i cannot offer an improved answer: Since JAVA 14 there is the concept of patternmatching for instance of https://openjdk.org/jeps/305. Just append a variable name like `if (obj instanceof C cVariable)` this allows you to use cVariable without casting it to C. – Dennis Mar 30 '23 at 09:26
440

Use Object.getClass. It returns the runtime type of the object. Here's how to call it using your example:

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

class Main {  
  public static void main(String args[]) { 
    C c = new C();
    Class clazz = c.getClass();
    System.out.println(clazz); 
  } 
}

Output:

class C

You can also compare two Class instances to see if two objects are the same type.

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

class Main {  
  public static void main(String args[]) { 
    B b = new B();
    Class c1 = b.getClass();
    C c = new C();
    Class c2 = c.getClass();
    System.out.println(c1 == c2); 
  } 
}
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
200

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.
icza
  • 389,944
  • 63
  • 907
  • 827
  • 7
    This is a really great summary of many of the pitfalls in the different methods. Thanks for such a complete write up! – Kelsin Aug 08 '15 at 17:55
36

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...

Johannes Weiss
  • 52,533
  • 16
  • 102
  • 136
  • 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 Feb 05 '16 at 07:23
22

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.

Yuval Adam
  • 161,610
  • 92
  • 305
  • 395
  • 3
    Yeah, probably 99% of the uses of getClass and instanceof can be avoided with polymorphic method calls. – Bill the Lizard Feb 12 '09 at 15:28
  • 3
    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. – carrier Feb 12 '09 at 15:32
  • That's generally the case in these situations, legacy code, bad design not in your ownership, etc... – Yuval Adam Feb 12 '09 at 15:37
  • 30
    Not nessecarily. Sometimes separation of interfaces is good. There are times when you want to know if A is a B, but you don't want to make it mandatory that A is a B, as only A is required for most functionality - B has optional functionality. – MetroidFan2002 Feb 12 '09 at 20:33
  • 8
    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. – StackOverflowed Jun 25 '12 at 15:17
  • 66
    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... – Adrián Pérez Sep 22 '13 at 17:32
  • 3
    some tasks like serializing, getting type maybe the simplest way? – tiboo Feb 18 '14 at 03:48
  • There are other cases especially hen discussing DI or producer frameworks where knowing the class types is necessary for binding. – ElfsЯUs Mar 08 '14 at 18:31
  • 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... – MBH Feb 05 '16 at 07:28
  • 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. – andand Feb 17 '16 at 22:20
  • 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 – KrystosTheOverlord Apr 23 '19 at 20:34
  • 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**. – JOE Jun 22 '21 at 02:49
16

We can use reflection in this case

objectName.getClass().getName();

Example:-

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String name = request.getClass().getName();
}

In this case you will get name of the class which object pass to HttpServletRequest interface refference variable.

Navnath Godse
  • 2,233
  • 2
  • 23
  • 32
user1884500
  • 269
  • 3
  • 3
13

There is also an .isInstance method on the "Class" class. if you get an object's class via myBanana.getClass() you can see if your object myApple is an instance of the same class as myBanana via

myBanana.getClass().isInstance(myApple)
Sk8erPeter
  • 6,899
  • 9
  • 48
  • 67
Andreas Petersson
  • 16,248
  • 11
  • 59
  • 91
3

checking with isinstance() would not be enough if you want to know in run time. use:

if(someObject.getClass().equals(C.class){
    // do something
}
Alon Gouldman
  • 3,025
  • 26
  • 29
1

I Used Java 8 generics to get what is the object instance at runtime rather than having to use switch case

 public <T> void print(T data) {
    System.out.println(data.getClass().getName()+" => The data is " + data);
}

pass any type of data and the method will print the type of data you passed while calling it. eg

    String str = "Hello World";
    int number = 10;
    double decimal = 10.0;
    float f = 10F;
    long l = 10L;
    List list = new ArrayList();
    print(str);
    print(number);
    print(decimal);
    print(f);
    print(l);
    print(list);

Following is the output

java.lang.String => The data is Hello World
java.lang.Integer => The data is 10
java.lang.Double => The data is 10.0
java.lang.Float => The data is 10.0
java.lang.Long => The data is 10
java.util.ArrayList => The data is []
Saurabh Verma
  • 627
  • 1
  • 14
  • 27
  • 1
    Using generics here, adds no value. Change the method declaration to `public void print(Object data)` and it will still work exactly the same. – Holger Apr 01 '22 at 06:57
1

You can use getSimpleName().

Let's say we have a object: Dog d = new Dog(),

The we can use below statement to get the class name: Dog. E.g.:

d.getClass().getSimpleName(); // return String 'Dog'.

PS: d.getClass() will give you the full name of your object.

Frank Liu
  • 151
  • 1
  • 5
1

your_instance.getClass().getSimpleName() will gives type name for example: String, Integer, Double, Boolean...

garawaa garawaa
  • 154
  • 1
  • 6
0

I use the blow function in my GeneralUtils class, check it may be useful

    public String getFieldType(Object o) {
    if (o == null) {
        return "Unable to identify the class name";
    }
    return o.getClass().getName();
}
Ahmed Salem
  • 1,687
  • 22
  • 26
0

use instanceof operator to find weather a object is of particular class or not.

booleanValue = (object instanceof class)

JDK 14 extends the instanceof operator: you can specify a binding variable; if the result of the instanceof operator is true, then the object being tested is assigned to the binding variable.

please visit official Java documentation for more reference.

Sample program to illustrate usage of instanceof operator :

import java.util.*;

class Foo{
    @Override 
    public String toString(){
        return "Bar";
    }
}

class Bar{
    public Object reference;
    @Override 
    public String toString(){
        return "Foo";
    }
}
public class InstanceofUsage{
    public static void main(final String ... $){
        final List<Object> list = new ArrayList<>();

        var out = System.out;

        list.add(new String("Foo Loves Bar"));
        list.add(33.3);
        list.add(404_404);
        list.add(new Foo());
        list.add(new Bar());

        for(final var o : list){
            if(o instanceof Bar b && b.reference == null){
                out.println("Bar : Null");
            }   
            if(o instanceof String s){
                out.println("String : "+s);
            }

            if(o instanceof Foo f){
                out.println("Foo : "+f);
            }
        }

    }
}

output:

$ javac InstanceofUsage.java && java InstanceofUsage 
String : Foo Loves Bar
Foo : Bar
Bar : Null
Udesh
  • 2,415
  • 2
  • 22
  • 32