java: Class.isInstance vs Class.isAssignableFrom


232

Lasciate clazzessere qualcheClass ed objessere alcuni Object.

È

clazz.isAssignableFrom(obj.getClass())

sempre uguale a

clazz.isInstance(obj)

?

In caso contrario, quali sono le differenze?


26
se obj == null, il secondo restituisce false, il primo no. ;)
Peter Lawrey,

21
@PeterLawrey, il primo lancerà un NullPointerExceptionif obj == null.
ryvantage

Ho trovato una risposta con alcuni esempi di hrere: mytechnotes.biz/2012/07/…
Paramesh Korrakuti,

4
Ai lettori: stai per entrare in un buco nero profondo, oscuro da cui non ti sfuggirai mai. Le differenze sono infinite. Rinuncia ora mentre puoi ancora: stackoverflow.com/q/496928/1599699
Andrew

@ParameshKorrakuti il ​​nome del dominio sta cambiando in tshikatshikaaa.blogspot.com/2012/07/…
Jérôme Verstrynge

Risposte:


222

clazz.isAssignableFrom(Foo.class)sarà vero ogni volta che la classe rappresentata clazzdall'oggetto è una superclasse o superinterfaccia diFoo .

clazz.isInstance(obj)sarà vero ogni volta che l'oggetto objè un'istanza della classe clazz.

Questo è:

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

è sempre vero fintanto che clazze non objsono null.


3
questo manca nel caso in cui il Foo sia lo stesso di clazz - nel qual caso ritorna vero: la risposta più votata da Pauls di seguito corregge questo problema
Rabarbaro

3
Sono d'accordo che quando clazz è un Foo, allora clazz.isAssignableFrom (Foo.class) è vero. Dove ho detto diversamente?
Uckelman,

5
@Gili Questo non è quello che ha detto Uckelman. Rileggi la sua risposta.
Puce,

2
Byte b = 3; Comparable.class.isAssignableFrom(b.getClass()) == Comparable.class.isInstance(b)); -> è vero anche per le interfacce.
Puce,

1
Tecnicità: Se objè nullallora clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)lancerà un NullPointerExceptione non tornerà true.
Andrew Macheret,

196

Entrambe le risposte sono nel campo da baseball ma nessuna delle due è una risposta completa.

MyClass.class.isInstance(obj)serve per controllare un'istanza. Restituisce vero quando il parametro obj è non nullo e può essere lanciato MyClasssenza alzare a ClassCastException. In altre parole, obj è un esempio diMyClass o delle sue sottoclassi.

MyClass.class.isAssignableFrom(Other.class)restituisce vero se MyClassè la stessa, o una superclasse o superinterfaccia di, Other. Otherpuò essere una classe o un'interfaccia. Risponde vero se Otherpuò essere convertito in a MyClass.

Un piccolo codice per dimostrare:

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

10
Perché nel tuo esempio "b isAssignableFrom a:" ma il codice è A.class.isAssignableFrom(B.class)? Ho confuso dall'output :)
Roman Truba

4
ummm ... in tutti i tuoi esempi "instanceOf" restituisce true iff "isAssignableFrom" restituisce true ... Non vedo la differenza in questo modo.
sviluppatore Android

2
Fai attenzione che il testo stampato non corrisponda al codice e può creare confusione ... Esempio: "System.out.println (" b isAssignableFrom a: "+ A.class.isAssignableFrom (B.class));"
polster

21
@Paul La risposta, così com'è, non è utile, perché il lettore rimane a chiedersi "qual è la differenza tra un oggetto che è un'istanza di una sottoclasse di una classe e il tipo di oggetto che è convertibile in classe?" Sicuramente, puoi vedere che hai lasciato al lettore tutte le domande dopo aver letto la tua risposta come aveva fatto quando è arrivato a questa pagina. Una risposta migliore spiegherebbe effettivamente la differenza (o la mancanza di essa). Se non c'è differenza, la risposta dovrebbe indicare direttamente "non c'è differenza pratica".
Aleksandr Dubinsky,

2
Ancora più importante, il lettore rimane a chiedersi che diamine usare per i loro scopi. Secondo i commenti nella domanda, isAssignableFrom()genera un NullPointerExceptionse l'oggetto è null, mentre isInstance()restituisce semplicemente false. Questa è la vera risposta.
Andrew,

6

Penso che il risultato per quei due dovrebbe essere sempre lo stesso. La differenza è che hai bisogno di un'istanza della classe da usare isInstancema solo l' Classoggetto da usare isAssignableFrom.


Questo non è vero al 100%. Comparable.class.isAssignableFrom(Byte.class) == truema Byte.class.isInstance(Comparable.class) == false. In altre parole, isInstance()non è simmetrico per le interfacce, ma solo per le sottoclassi.
Gili,

6
@Gili: hai sbagliato un po 'lì. Byte.class.isInstance(Comparable.class)è falso perché un Classoggetto non è un'istanza di Byte. Il confronto corretto con Comparable.class.isAssignableFrom(Byte.class)è Comparable.class.isInstance((byte) 1), che è vero.
ColinD,

1
Non sono d'accordo. Se cerchi il Javadoc Bytescoprirai che si estende Numbered è una classe. (byte) 1non è equivalente a Byte. Il primo è un primitivo. Quest'ultima è una classe.
Gili,

2
@Gili: Autoboxing lancia primitiva bytea Bytecausa del tipo di parametro di isInstanceè Object.
ColinD

2
Va bene. Il mio punto originale era che le chiamate non sono esattamente simmetriche l'una con l'altra, ma dopo aver riletto la tua risposta non hai mai fatto questa affermazione, quindi hai ragione.
Gili

6

Per brevità, possiamo comprendere queste due API come di seguito:

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

Se X e Ysono la stessa classe o Xè Yla super classe o la super interfaccia, restituisce true, altrimenti false.

  1. X.class.isInstance(y)

Say yè un'istanza di classe Y, se XeY sono la stessa classe, oppure Xè Ysuperclasse o super interfaccia, restituisce vero, altrimenti falso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.