2010-10-16 18 views
180

Niech clazz być niektóre Class i obj być niektóre Object.java: Class.isInstance vs Class.isAssignableFrom

Czy

clazz.isAssignableFrom(obj.getClass()) 

zawsze taka sama jak

clazz.isInstance(obj) 

?

Jeśli nie, jakie są różnice?

+19

jeśli obj == null, druga zwraca wartość false, pierwsza nie. ;) –

+15

@PeterLawrey, pierwszy rzuci 'NullPointerException', jeśli' obj == null'. – ryvantage

+0

Znaleziono kilka odpowiedzi na próbki z hrere: http://www.mytechnotes.biz/2012/07/java-instanceof-isassignablefrom-or.html –

Odpowiedz

149

clazz.isAssignableFrom(Foo.class) będzie prawdziwe, gdy klasa reprezentowana przez obiekt clazz jest nadklasą lub superinterfejsem Foo.

clazz.isInstance(obj) będzie prawdziwe, gdy obiekt obj jest instancją klasy clazz.

Czyli:

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

jest zawsze prawdziwa.

+2

to pomija przypadek, w którym Foo jest tym samym, co clazz - w takim przypadku zwraca true: Najczęściej komentowana odpowiedź Paula poniżej koryguje to – Rhubarb

+3

Zgadzam się, że gdy clazz jest Foo, to clazz.isAssignableFrom (Foo.class) jest prawdziwe . Gdzie powiedziałem inaczej? – uckelman

+0

To nie jest w 100% prawdziwe. 'Comparable.class.isAssignableFrom (Byte.class) == true' ale' Byte.class.isInstance (Comparable.class) == false'. Innymi słowy, 'isInstance()' nie jest symetryczne dla interfejsów, tylko dla podklas. – Gili

4

Myślę, że wynik dla tych dwojga powinien być zawsze taki sam. Różnica polega na tym, że potrzebujesz instancji klasy, aby użyć isInstance, ale tylko obiektu Class do używania isAssignableFrom.

+0

To nie jest w 100% prawdziwe. 'Comparable.class.isAssignableFrom (Byte.class) == true' ale' Byte.class.isInstance (Comparable.class) == false'. Innymi słowy, 'isInstance()' nie jest symetryczne dla interfejsów, tylko dla podklas. – Gili

+4

@Gili: Tam jest trochę źle. 'Byte.class.isInstance (Comparable.class)' ma wartość false, ponieważ obiekt 'Class' nie jest instancją' Byte'. Prawidłowe porównanie z 'Comparable.class.isAssignableFrom (Byte.class)' to "Comparable.class.isInstance ((byte) 1)", co jest prawdą. – ColinD

+1

Nie zgadzam się. Jeśli spojrzysz na Javadoc 'Byte', odkryjesz, że rozszerza on' Number' i jest klasą. '(byte) 1' nie jest równoważne' Byte'. Ten pierwszy jest prymitywny. Ta ostatnia jest klasą. – Gili

157

Obie odpowiedzi są dostępne w sklepie, ale żadna z nich nie jest kompletna.

MyClass.class.isInstance(obj) służy do sprawdzania instancji. Zwraca wartość true, gdy parametr obj jest wartością inną niż null i można go przenieść do MyClass bez podnoszenia wartości ClassCastException. Innymi słowy, obj jest instancją MyClass lub jej podklasami.

MyClass.class.isAssignableFrom(Other.class) zwróci true, jeśli MyClass jest takie samo lub superklasy lub superinterfejsu, Other. Other może być klasą lub interfejsem. Odpowiada to prawdzie, jeśli można przekonwertować Other na MyClass.

Trochę kodu wykazać:

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

a wyjście:

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

Linie od trzeciej do ostatniej i drugiej do ostatniej mówią "bArr isInstance aArr", ale kod jest inny. –

+5

Dlaczego w twoim przykładzie "b isAssignableFrom a:", ale kod jest "A.class.isAssignableFrom (B.class)"? Pomyliłem się przez wyjście :) –

+0

MyClass.class.isInstance (obj) będzie również działał dla interfejsów: _Jeśli ten obiekt Class reprezentuje interfejs, ta metoda zwraca wartość true, jeśli klasa lub dowolna nadklasa podanego argumentu Object implementuje ten interfejs. – Patrick

3

Dla zwięzłości, możemy zrozumieć te dwa API jak poniżej:

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

Jeśli X i Y są tą samą klasą lub X jest super-klasą super interfejsu Y, zwracana jest wartość true, w przeciwnym razie false.

  1. X.class.isInstance (y):

Powiedzmy y jest instancją klasy Y, jeśli X i Y są tą samą klasą lub X jest super-klasą super interfejsu Y, zwracają true, w przeciwnym razie false.