2010-10-16 2 views
180

Дайте clazz быть Class и obj be some Object.java: Class.isInstance vs Class.isAssignable From

Является

clazz.isAssignableFrom(obj.getClass()) 

всегда совпадает с

clazz.isInstance(obj) 

?

Если нет, то в чем отличия?

+19

если obj == null, второй возвращает false, первый - нет. ;) –

+15

@PeterLawrey, первый будет вызывать 'NullPointerException', если' obj == null'. – ryvantage

+0

Нашел ответ с образцами из hrere: http://www.mytechnotes.biz/2012/07/java-instanceof-isassignablefrom-or.html –

ответ

149

clazz.isAssignableFrom(Foo.class) будет истинным, если класс, представленный объектом clazz, является суперклассом или суперинтерфейсом Foo.

clazz.isInstance(obj) будет истинным всякий раз, когда объект obj является экземпляром класса clazz.

То есть:

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

всегда верно.

+2

это пропустит случай, когда Foo такой же, как clazz - в этом случае он возвращает true: Pauls top-voted answer below исправляет это – Rhubarb

+3

Я согласен, что когда clazz является Foo, тогда clazz.isAssignableFrom (Foo.class) истинно , Где я сказал иначе? – uckelman

+0

Это не на 100% верно. 'Comparable.class.isAssignableFrom (Byte.class) == true', но' Byte.class.isInstance (Comparable.class) == false'. Другими словами, 'isInstance()' не является симметричным для интерфейсов, только для подклассов. – Gili

4

Я думаю, что результат для этих двух должен всегда быть одним и тем же. Разница в том, что вам нужен экземпляр класса для использования isInstance, но только для объекта Class для использования isAssignableFrom.

+0

Это не 100% истинно. 'Comparable.class.isAssignableFrom (Byte.class) == true', но' Byte.class.isInstance (Comparable.class) == false'. Другими словами, 'isInstance()' не является симметричным для интерфейсов, только для подклассов. – Gili

+4

@Gili: У тебя там немного не так. 'Byte.class.isInstance (Comparable.class)' false, потому что объект 'Class' не является экземпляром' Byte'. Правильное сравнение с 'Comparable.class.isAssignableFrom (Byte.class)' является 'Comparable.class.isInstance ((byte) 1)', что верно. – ColinD

+1

Я не согласен. Если вы посмотрите на Javadoc 'Byte', вы обнаружите, что он расширяет« Number »и является классом. '(byte) 1' не эквивалентен' Byte'. Первый - примитив. Последний класс. – Gili

157

Оба ответа находятся на футбольном поле, но ни один из них не является полным ответом.

MyClass.class.isInstance(obj) предназначен для проверки экземпляра. Он возвращает true, когда параметр obj не равен нулю и может быть отброшен до MyClass без повышения ClassCastException. Другими словами, obj является экземпляром MyClass или его подклассами.

MyClass.class.isAssignableFrom(Other.class) вернет true, если MyClass - это то же самое, что и суперкласс или суперинтерфейс, Other. Other может быть классом или интерфейсом. Он отвечает, если Other можно преобразовать в MyClass.

Немного кода, чтобы продемонстрировать:

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

И вывод:

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

В третьей и второй строках строки говорят «bArr isInstance aArr», но код отличается. –

+5

Почему в вашем примере «b isAssignableFrom a:», но код «A.class.isAssignableFrom (B.class)»? Я запутался в выходе :) –

+0

MyClass.class.isInstance (obj) также будет работать для интерфейсов: _ Если этот объект класса представляет собой интерфейс, этот метод возвращает true, если класс или любой суперкласс указанного аргумента объекта реализует этот интерфейс. – Patrick

3

Для краткости, мы можем понять эти два API, как показано ниже:

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

Если X и Y являются одним и тем же классом, либо X является супер-классом Y или супер-интерфейсом, верните true, иначе false.

  1. X.class.isInstance (y):

Скажите, что y является экземпляром класса Y, если X и Y являются одним и тем же классом, или X является суперклассическим или супер-интерфейсом Y, верните true, иначе false.