java: Class.isInstance vs Class.isAssignableFrom


232

Pozwól clazzbyć trochę Classi objbądź trochę Object.

Jest

clazz.isAssignableFrom(obj.getClass())

zawsze taki sam jak

clazz.isInstance(obj)

?

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


26
jeśli obj == null, drugi zwraca false, pierwszy nie. ;)
Peter Lawrey,

21
@PeterLawrey, pierwszy rzuci NullPointerExceptionif obj == null.
ryvantage

Znaleziono odpowiedź na próbki z hrere: mytechnotes.biz/2012/07/...
Paramesh Korrakuti

4
Do czytelników: masz zamiar wejść do głębokiej, ciemnej, czarnej dziury, z której nigdy nie uciekniesz. Różnice są nieskończone. Zrezygnuj teraz, póki jeszcze możesz: stackoverflow.com/q/496928/1599699
Andrew

@ParameshKorrakuti nazwa domeny zmienia się na tshikatshikaaa.blogspot.com/2012/07/…
Jérôme Verstrynge

Odpowiedzi:


222

clazz.isAssignableFrom(Foo.class)będzie prawdą, ilekroć klasa reprezentowana przez clazzobiekt jest nadklasą lub superinterface Foo.

clazz.isInstance(obj)będzie prawdziwe, ilekroć obiekt objjest instancją klasy clazz.

To jest:

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

zawsze jest prawdą tak długo, jak długo clazzi objsą niepustych.


3
pomija to przypadek, w którym Foo jest tym samym co clazz - w którym to przypadku zwraca prawdę: Pauls, który uzyskał najwyższą głosowanie, naprawia to
Rhubarb

3
Zgadzam się, że jeśli clazz jest Foo, to clazz.isAssignableFrom (Foo.class) jest prawdą. Gdzie powiedziałem inaczej?
uckelman

5
@Gili Nie to powiedział Uckelman. Przeczytaj ponownie jego odpowiedź.
Puce

2
Byte b = 3; Comparable.class.isAssignableFrom(b.getClass()) == Comparable.class.isInstance(b)); -> dotyczy to również interfejsów.
Puce

1
Technika: Jeśli objtak, nullto clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)rzuci NullPointerExceptiona nie wróci true.
Andrew Macheret,

196

Obie odpowiedzi są na boisku, ale żadna nie jest kompletną odpowiedzią.

MyClass.class.isInstance(obj)służy do sprawdzania instancji. Zwraca true, gdy parametr obj ma wartość MyClassinną niż null i można do niego rzutować bez podnoszenia a ClassCastException. Innymi słowy, obj jest instancją MyClasslub jej podklasami.

MyClass.class.isAssignableFrom(Other.class)zwróci true, jeśli MyClassjest taka sama jak, albo nadrzędnej lub superinterface z, Other. Othermoże być klasą lub interfejsem. To prawda, jeśli Othermożna je przekonwertować na MyClass.

Mały kod do zademonstrowania:

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
Dlaczego w twoim przykładzie „b jestAssignableFrom a:”, ale kod jest A.class.isAssignableFrom(B.class)? Myliłem przez wynik :)
Roman Truba

4
ummm ... we wszystkich twoich przykładach „instanceOf” zwraca true iff „isAssignableFrom” zwraca true… Nie widzę różnicy w ten sposób.
programista Androida

2
Uważaj, aby wydrukowany tekst nie zgadzał się z kodem i może być mylący ... Przykład: „System.out.println („ b isAssignableFrom a: ”+ A.class.isAssignableFrom (B.class));”
polster

21
@Paul Odpowiedź nie jest pomocna, ponieważ czytelnik nie zastanawia się „jaka jest różnica między obiektem będącym instancją podklasy klasy a typem obiektu konwertowalnym na klasę?” Z pewnością widać, że po przeczytaniu odpowiedzi pozostawiłeś czytelnikowi tyle pytań, ile on przyszedł na tę stronę. Lepsza odpowiedź faktycznie wyjaśniłaby różnicę (lub jej brak). Jeśli nie ma różnicy, odpowiedź powinna bezpośrednio brzmieć: „nie ma praktycznej różnicy”.
Aleksandr Dubinsky

2
Co ważniejsze, czytelnik zastanawia się, do czego do cholery wykorzystać. Zgodnie z komentarzami w pytaniu isAssignableFrom()wyrzuca a, NullPointerExceptionjeśli obiekt ma wartość null, a isInstance()po prostu zwraca false. To jest prawdziwa odpowiedź.
Andrew

6

Myślę, że wynik dla tych dwóch powinien zawsze być taki sam. Różnica polega na tym, że potrzebujesz instancji klasy do użycia, isInstanceale tylko Classobiektu do użycia isAssignableFrom.


To nie jest w 100% prawda. Comparable.class.isAssignableFrom(Byte.class) == trueale Byte.class.isInstance(Comparable.class) == false. Innymi słowy, isInstance()nie jest symetryczny dla interfejsów, tylko dla podklas.
Gili

6
@Gili: Jest tam trochę źle. Byte.class.isInstance(Comparable.class)jest fałszem, ponieważ Classobiekt nie jest instancją Byte. Prawidłowe porównanie 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, odkryje, że rozszerza się Numberi jest klasą. (byte) 1nie jest równoważne z Byte. Ten pierwszy jest prymitywny. Ten ostatni jest klasą.
Gili

2
@Gili: Autoboxing rzutuje prymitywnie bytena, Byteponieważ typ parametru isInstanceto Object.
ColinD

2
W porządku. Mój pierwotny punkt był taki, że połączenia nie są dokładnie symetryczne względem siebie, ale po ponownym przeczytaniu odpowiedzi nigdy nie złożyłeś tego stwierdzenia, więc masz rację.
Gili

6

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

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

Jeśli Xi Ysą tą samą klasą lub XYsuperklasą lub super interfejsem, zwróć true, w przeciwnym razie false.

  1. X.class.isInstance(y)

Powiedz, że yjest instancją klasy Y, jeśli Xi Ysą tą samą klasą, lub Xjest Ysuperklasą lub super interfejsem, zwróć true, w przeciwnym razie false.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.