java: Class.isInstance vs Class.isAssignableFrom

232

Soyons clazzcertains Classet objsoyez certains Object.

Est

clazz.isAssignableFrom(obj.getClass())

toujours le même que

clazz.isInstance(obj)

?

Sinon, quelles sont les différences?

Albert
la source
26
si obj == null, le second retourne false, le premier non. ;)
Peter Lawrey
21
@PeterLawrey, le premier lancera un NullPointerExceptionif obj == null.
ryvantage
Trouvé une réponse avec des échantillons de ici: mytechnotes.biz/2012/07/…
Paramesh Korrakuti
4
Aux lecteurs: vous êtes sur le point d'entrer dans un trou noir, profond et noir dont vous ne vous échapperez jamais. Les différences sont infinies. Abandonnez maintenant tant que vous le pouvez: stackoverflow.com/q/496928/1599699
Andrew
@ParameshKorrakuti le nom de domaine change en tshikatshikaaa.blogspot.com/2012/07/…
Jérôme Verstrynge

Réponses:

222

clazz.isAssignableFrom(Foo.class)sera vrai chaque fois que la classe représentée par l' clazzobjet est une superclasse ou une superinterface de Foo.

clazz.isInstance(obj)sera vrai chaque fois que l'objet objest une instance de la classe clazz.

C'est:

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

est toujours vrai tant clazzet ne objsont pas nuls.

uckelman
la source
3
cela manque le cas où le Foo est le même que le clazz - auquel cas il revient vrai: la réponse la plus votée de Paul ci-dessous corrige cela
Rhubarbe
3
Je suis d'accord que lorsque clazz est un Foo, alors clazz.isAssignableFrom (Foo.class) est vrai. Où ai-je dit le contraire?
uckelman
5
@Gili Ce n'est pas ce qu'a dit uckelman. Veuillez relire sa réponse.
Puce
2
Byte b = 3; Comparable.class.isAssignableFrom(b.getClass()) == Comparable.class.isInstance(b)); -> c'est vrai aussi pour les interfaces.
Puce
1
Technicité: Si objc'est nullalors clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)jettera un NullPointerExceptionet ne reviendra pas true.
Andrew Macheret
196

Les deux réponses sont dans la boule mais aucune n'est une réponse complète.

MyClass.class.isInstance(obj)sert à vérifier une instance. Il retourne vrai lorsque le paramètre obj est non nul et peut être converti en MyClasssans augmenter a ClassCastException. En d'autres termes, obj est une instance de MyClassou de ses sous-classes.

MyClass.class.isAssignableFrom(Other.class)retourne vrai si MyClassest le même que, ou une superclasse ou superinterface de, Other. Otherpeut être une classe ou une interface. Il répond vrai si Otherpeut être converti en a MyClass.

Un petit code pour démontrer:

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
    }
}
Paul
la source
10
Pourquoi dans votre exemple "b isAssignableFrom a:" mais le code l'est A.class.isAssignableFrom(B.class)? Je suis confus par la sortie :)
Roman Truba
4
ummm ... dans tous vos exemples "instanceOf" retourne vrai si "isAssignableFrom" retourne vrai ... Je ne vois pas la différence de cette façon.
développeur Android
2
Attention, le texte imprimé ne correspond pas au code et peut prêter à confusion ... Exemple: "System.out.println (" b isAssignableFrom a: "+ A.class.isAssignableFrom (B.class));"
polster
21
@Paul La réponse, en l'état, n'est pas utile, car le lecteur se demande "quelle est la différence entre un objet étant une instance d'une sous-classe d'une classe et le type de l'objet convertible en classe?" Vous pouvez sûrement constater que vous avez laissé au lecteur autant de questions après avoir lu votre réponse qu'il en avait lors de son arrivée sur cette page. Une meilleure réponse expliquerait en fait la différence (ou son absence). S'il n'y a pas de différence, la réponse doit indiquer directement "il n'y a pas de différence pratique".
Aleksandr Dubinsky
2
Plus important encore, le lecteur se demande ce qu'il convient d'utiliser à leurs fins. Selon les commentaires de la question, isAssignableFrom()lance un NullPointerExceptionsi l'objet est nul, tandis isInstance()que renvoie simplement faux. Voilà la vraie réponse.
Andrew
6

Je pense que le résultat pour ces deux devrait toujours être le même. La différence est que vous avez besoin d'une instance de la classe à utiliser, isInstancemais uniquement de l' Classobjet à utiliser isAssignableFrom.

ColinD
la source
Ce n'est pas vrai à 100%. Comparable.class.isAssignableFrom(Byte.class) == truemais Byte.class.isInstance(Comparable.class) == false. En d'autres termes, isInstance()n'est pas symétrique pour les interfaces, uniquement pour les sous-classes.
Gili
6
@Gili: Vous vous trompez un peu là-bas. Byte.class.isInstance(Comparable.class)est faux car un Classobjet n'est pas une instance de Byte. La comparaison correcte avec Comparable.class.isAssignableFrom(Byte.class)est Comparable.class.isInstance((byte) 1), ce qui est vrai.
ColinD
1
Je ne suis pas d'accord. Si vous recherchez le Javadoc, Bytevous découvrirez qu'il s'étend Numberet est une classe. (byte) 1n'est pas équivalent à Byte. Le premier est un primitif. Ce dernier est une classe.
Gili
2
@Gili: Autoboxing convertit la primitive byteen Bytecar le type de paramètre isInstanceest Object.
ColinD
2
D'accord. Mon point de départ était que les appels ne sont pas exactement symétriques, mais après avoir relu votre réponse, vous n'avez jamais fait cette affirmation, vous avez donc raison.
Gili
6

Par souci de concision, nous pouvons comprendre ces deux API comme ci-dessous:

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

Si Xet Ysont la même classe, ou Xest Yla super classe ou la super interface, retournez true, sinon, false.

  1. X.class.isInstance(y)

Say yest une instance de classe Y, si Xet Ysont la même classe, ou Xest Yla super classe ou la super interface de, renvoie true, sinon, false.

Ensoleillé
la source