260

Let clazz be some Class and obj be some Object.

Is

clazz.isAssignableFrom(obj.getClass())

always the same as

clazz.isInstance(obj)

?

If not, what are the differences?

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
Albert
  • 65,406
  • 61
  • 242
  • 386
  • 31
    if obj == null, the second returns false, the first does not. ;) – Peter Lawrey Oct 19 '10 at 19:07
  • 23
    @PeterLawrey, the first will throw a `NullPointerException` if `obj == null`. – ryvantage Jan 09 '14 at 22:40
  • Found some answer with samples from hrere : http://www.mytechnotes.biz/2012/07/java-instanceof-isassignablefrom-or.html – Paramesh Korrakuti Oct 19 '15 at 09:08
  • 4
    To the readers: you are about to enter a deep, dark, black hole from which you will never escape. The differences are endless. Give up now while you still can: https://stackoverflow.com/q/496928/1599699 – Andrew Oct 17 '17 at 12:26
  • @ParameshKorrakuti the domain name is changing to https://tshikatshikaaa.blogspot.com/2012/07/java-instanceof-isassignablefrom-or.html – Jérôme Verstrynge Feb 09 '20 at 18:59

4 Answers4

251

clazz.isAssignableFrom(Foo.class) will be true whenever the class represented by the clazz object is a superclass or superinterface of Foo.

clazz.isInstance(obj) will be true whenever the object obj is an instance of the class clazz.

That is:

clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)

is always true so long as clazz and obj are nonnull.

uckelman
  • 25,298
  • 8
  • 64
  • 82
  • 4
    this misses the case where the Foo is the same as clazz - in which case it returns true: Pauls top-voted answer below corrects this – Rhubarb Mar 21 '13 at 14:18
  • 3
    I agree that when clazz is a Foo, then clazz.isAssignableFrom(Foo.class) is true. Where did I say otherwise? – uckelman Apr 02 '13 at 09:09
  • This isn't 100% true. `Comparable.class.isAssignableFrom(Byte.class) == true` but `Byte.class.isInstance(Comparable.class) == false`. In other words, `isInstance()` is not symmetric for interfaces, only for subclasses. – Gili Feb 28 '14 at 05:55
  • 6
    @Gili This isn't what uckelman said. Please re-read his answer. – Puce Mar 03 '14 at 11:03
  • 2
    `Byte b = 3; Comparable.class.isAssignableFrom(b.getClass()) == Comparable.class.isInstance(b));` -> it's true also for interfaces. – Puce Mar 03 '14 at 11:05
  • 1
    Technicality: If `obj` is `null` then `clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)` will throw a `NullPointerException` and not return `true`. – Andrew Macheret Apr 23 '18 at 22:14
207

Both answers are in the ballpark but neither is a complete answer.

MyClass.class.isInstance(obj) is for checking an instance. It returns true when the parameter obj is non-null and can be cast to MyClass without raising a ClassCastException. In other words, obj is an instance of MyClass or its subclasses.

MyClass.class.isAssignableFrom(Other.class) will return true if MyClass is the same as, or a superclass or superinterface of, Other. Other can be a class or an interface. It answers true if Other can be converted to a MyClass.

A little code to demonstrate:

public class NewMain
{
    public static void main(String[] args)
    {
        NewMain nm = new NewMain();
        nm.doit();
    }

    class A { }

    class B extends A { }

    public void doit()
    {
        A myA = new A();
        B myB = new B();
        A[] aArr = new A[0];
        B[] bArr = new B[0];

        System.out.println("b instanceof a: " + (myB instanceof A)); // true
        System.out.println("b isInstance a: " + A.class.isInstance(myB)); //true
        System.out.println("a isInstance b: " + B.class.isInstance(myA)); //false
        System.out.println("b isAssignableFrom a: " + A.class.isAssignableFrom(B.class)); //true
        System.out.println("a isAssignableFrom b: " + B.class.isAssignableFrom(A.class)); //false
        System.out.println("bArr isInstance A: " + A.class.isInstance(bArr)); //false
        System.out.println("bArr isInstance aArr: " + aArr.getClass().isInstance(bArr)); //true
        System.out.println("bArr isAssignableFrom aArr: " + aArr.getClass().isAssignableFrom(bArr.getClass())); //true
    }
}
David Marciel
  • 865
  • 1
  • 12
  • 29
Paul
  • 19,704
  • 14
  • 78
  • 96
  • 1
    The 3rd-to-last and 2nd-to-last lines both say `bArr isInstance aArr` but the code is different. – Brad Cupit May 29 '13 at 01:32
  • 10
    Why in your example "b isAssignableFrom a:" but code is `A.class.isAssignableFrom(B.class)`? I confused by output :) – Roman Truba Jan 30 '14 at 11:45
  • MyClass.class.isInstance(obj) will also work for interfaces: _If this Class object represents an interface, this method returns true if the class or any superclass of the specified Object argument implements this interface._ – Patrick May 03 '14 at 00:07
  • 4
    ummm... in all your examples "instanceOf" returns true iff "isAssignableFrom" returns true... I don't see the difference this way. – android developer May 05 '14 at 18:46
  • System.out.println("b isAssignableFrom a: " + A.class.isAssignableFrom(B.class)); System.out.println("a isAssignableFrom b: " + B.class.isAssignableFrom(A.class)); should be System.out.println("b isAssignableFrom a: " + B.class.isAssignableFrom(A.class)); System.out.println("a isAssignableFrom b: " + A.class.isAssignableFrom(B.class)); – unify Aug 31 '14 at 18:38
  • This doesn't answer the question whether `clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)` is true for all `obj != null`. – Gedrox Sep 03 '14 at 09:48
  • 3
    Be careful the text printed out doesn't match the code and can be confusing ... Example: "System.out.println("b isAssignableFrom a: " + A.class.isAssignableFrom(B.class));" – polster Apr 01 '15 at 21:06
  • 1
    This fails to answer the question, namely, "what are the differences?" Everyone here has (hopefully) read the javadoc. What we need is some analysis. – Aleksandr Dubinsky Feb 08 '16 at 07:36
  • @AleksandrDubinsky, what differences or analysis areyou looking for? – Paul Feb 08 '16 at 14:42
  • 26
    @Paul The answer, as is, is not helpful, because the reader is left wondering "what is the difference between an object being an instance of a subclass of a class and the object's type being convertible to the class?" Surely, you can see that you've left the reader with as many questions after reading your answer as he had when arriving at this page. A better answer would actually explain the difference (or lack thereof). If there is no difference, the answer should directly state, "there is no practical difference." – Aleksandr Dubinsky Feb 10 '16 at 11:34
  • 3
    More importantly, the reader is left wondering what the heck to use for their purposes. According to the comments in the question, `isAssignableFrom()` throws a `NullPointerException` if the object is null, whereas `isInstance()` just returns false. That's the real answer. – Andrew Oct 17 '17 at 12:14
9

I think the result for those two should always be the same. The difference is that you need an instance of the class to use isInstance but just the Class object to use isAssignableFrom.

ColinD
  • 108,630
  • 30
  • 201
  • 202
  • This isn't 100% true. `Comparable.class.isAssignableFrom(Byte.class) == true` but `Byte.class.isInstance(Comparable.class) == false`. In other words, `isInstance()` is not symmetric for interfaces, only for subclasses. – Gili Feb 28 '14 at 05:56
  • 10
    @Gili: You've got it a bit wrong there. `Byte.class.isInstance(Comparable.class)` is false because a `Class` object is not an instance of `Byte`. The correct comparison to `Comparable.class.isAssignableFrom(Byte.class)` is `Comparable.class.isInstance((byte) 1)`, which is true. – ColinD Feb 28 '14 at 17:17
  • 1
    I disagree. If you look up the Javadoc of `Byte` you will discover it extends `Number` and is a class. `(byte) 1` is not equivalent to `Byte`. The former is a primitive. The latter is a Class. – Gili Feb 28 '14 at 22:11
  • 2
    @Gili: Autoboxing casts primitive `byte` to `Byte` because the parameter type of `isInstance` is `Object`. – ColinD Feb 28 '14 at 22:13
  • 2
    Okay. My original point was that the calls are not exactly symmetric to each other, but having re-read your answer you never made this assertion so you're right. – Gili Mar 02 '14 at 16:28
8

For brevity, we can understand these two APIs like below:

  1. X.class.isAssignableFrom(Y.class)

If X and Y are the same class, or X is Y's super class or super interface, return true, otherwise, false.

  1. X.class.isInstance(y)

Say y is an instance of class Y, if X and Y are the same class, or X is Y's super class or super interface, return true, otherwise, false.

Genhis
  • 1,484
  • 3
  • 27
  • 29
Sunny
  • 181
  • 1
  • 7
  • So you are saying isAssignableFrom takes class and isInstance takes instance. That is the only difference? – Varun May 24 '22 at 06:03