2010-10-16 14 views
180

Deje que clazz sea un Class y obj sea un Object.java: Class.isInstance vs Class.isAssignableFrom

Es

clazz.isAssignableFrom(obj.getClass()) 

siempre el mismo que

clazz.isInstance(obj) 

?

Si no, ¿cuáles son las diferencias?

+19

if obj == null, el segundo devuelve falso, el primero no. ;) –

+15

@PeterLawrey, el primero arrojará una 'NullPointerException' si' obj == null'. – ryvantage

+0

Encontré una respuesta con ejemplos de hrere: http://www.mytechnotes.biz/2012/07/java-instanceof-isassignablefrom-or.html –

Respuesta

149

clazz.isAssignableFrom(Foo.class) será verdadero siempre que la clase representada por el objeto clazz sea una superclase o superinterfaz de Foo.

clazz.isInstance(obj) será verdadero siempre que el objeto obj sea una instancia de la clase clazz.

Eso es:

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

siempre es cierto.

+2

se echa de menos el caso donde el Foo es lo mismo que clazz - en cuyo caso devuelve verdadero: la respuesta de Pauls más votada a continuación corrige esto – Rhubarb

+3

Acepto que cuando clazz es un Foo, entonces clazz.isAssignableFrom (Foo.class) es verdadero . ¿Dónde dije lo contrario? – uckelman

+0

Esto no es 100% cierto. 'Comparable.class.isAssignableFrom (Byte.class) == true' pero' Byte.class.isInstance (Comparable.class) == false'. En otras palabras, 'isInstance()' no es simétrico para interfaces, solo para subclases. – Gili

4

Creo que el resultado para esos dos debería ser siempre el mismo. La diferencia es que necesita una instancia de la clase para usar isInstance pero solo el objeto Class para usar isAssignableFrom.

+0

Esto no es 100% cierto. 'Comparable.class.isAssignableFrom (Byte.class) == true' pero' Byte.class.isInstance (Comparable.class) == false'. En otras palabras, 'isInstance()' no es simétrico para interfaces, solo para subclases. – Gili

+4

@Gili: Lo tienes un poco mal allí. 'Byte.class.isInstance (Comparable.class)' es falso porque un objeto 'Class' no es una instancia de' Byte'. La comparación correcta con 'Comparable.class.isAssignableFrom (Byte.class)' es 'Comparable.class.isInstance ((byte) 1)', que es verdadero. – ColinD

+1

No estoy de acuerdo. Si busca el Javadoc de 'Byte', descubrirá que se extiende' Number' y es una clase. '(byte) 1' no es equivalente a' Byte'. El primero es un primitivo. Este último es una Clase. – Gili

157

Ambas respuestas están en el estadio pero ninguna es una respuesta completa.

MyClass.class.isInstance(obj) es para verificar una instancia. Devuelve true cuando el parámetro obj no es nulo y se puede convertir a MyClass sin generar un ClassCastException. En otras palabras, obj es una instancia de MyClass o sus subclases.

MyClass.class.isAssignableFrom(Other.class) devolverá verdadero si MyClass es lo mismo que, o una superclase o superinterfaz de, Other. Other puede ser una clase o una interfaz. Responde verdadero si Other se puede convertir a MyClass.

un poco de código para demostrar:

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

    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)); 
     System.out.println("b isInstance a: " + A.class.isInstance(myB)); 
     System.out.println("a isInstance b: " + B.class.isInstance(myA)); 
     System.out.println("b isAssignableFrom a: " + A.class.isAssignableFrom(B.class)); 
     System.out.println("a isAssignableFrom b: " + B.class.isAssignableFrom(A.class)); 
     System.out.println("bArr isInstance A: " + A.class.isInstance(bArr)); 
     System.out.println("bArr isInstance aArr: " + aArr.getClass().isInstance(bArr)); 
     System.out.println("bArr isAssignableFrom aArr: " + aArr.getClass().isAssignableFrom(bArr.getClass())); 
    } 

    class A 
    { 
    } 

    class B extends A 
    { 
    } 
} 

Y la salida:

b instanceof a: true 
b isInstance a: true 
a isInstance b: false 
b isAssignableFrom a: true 
a isAssignableFrom b: false 
bArr isInstance A: false 
bArr isInstance aArr: true 
bArr isAssignableFrom aArr: true 
+1

La penúltima y la penúltima líneas dicen 'bArr isInstance aArr' pero el código es diferente. –

+5

¿Por qué en su ejemplo "b isAssignableFrom a:" pero el código es 'A.class.isAssignableFrom (B.class)'? Confundí por salida :) –

+0

MyClass.class.isInstance (obj) también funcionará para las interfaces: _Si este objeto de clase representa una interfaz, este método devuelve verdadero si la clase o cualquier superclase del argumento de objeto especificado implementa esta interfaz._ – Patrick

3

Por razones de brevedad, podemos entender estas dos API, como a continuación:

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

Si X e Y son de la misma clase, o X es la superclase o súper interfaz de Y, devuelve verdadero, de lo contrario, falso.

  1. X.class.isInstance (y):

Say y es una instancia de la clase Y, si X e Y son de la misma clase, o X es superclase o súper interfaz, devuelve verdadero; de lo contrario, es falso.