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.