java: Class.isInstance vs Class.isAssignableFrom


232

Дозвольте clazzбути деякими Classі objбути деякими Object.

Є

clazz.isAssignableFrom(obj.getClass())

завжди те саме, що

clazz.isInstance(obj)

?

Якщо ні, то які відмінності?


26
якщо obj == null, другий повертає false, перший не робить. ;)
Пітер Лоурі

21
@PeterLawrey, перший кине NullPointerExceptionif obj == null.
ривантаж

Знайшов деяку відповідь із зразками з hrere: mytechnotes.biz/2012/07/…
Paramesh Korrakuti

4
Читачам: ви збираєтеся ввести глибоку, темну, чорну діру, з якої ніколи не втечеш. Відмінності нескінченні. Відмовтесь зараз, поки ще можете: stackoverflow.com/q/496928/1599699
Ендрю

@ParameshKorrakuti доменне ім’я змінюється на tshikatshikaaa.blogspot.com/2012/07/…
Jérôme Verstrynge

Відповіді:


222

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

clazz.isInstance(obj)буде істинним, коли об'єкт objє екземпляром класу clazz.

Це є:

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

завжди вірно , так довго , як clazzі objв ненульових.


3
це пропускає випадок, коли Foo - це те саме, що і clazz - і в цьому випадку воно повертається істинним: відповідь Паульса, що відповідає вище, виправляє це
Rhubarb

3
Я погоджуюсь, що коли clazz є Foo, тоді clazz.isAssignableFrom (Foo.class) є істинним. Де я сказав інакше?
uckelman

5
@Gili Це не те, що сказав uckelman. Будь ласка, перечитайте його відповідь.
Пуче

2
Byte b = 3; Comparable.class.isAssignableFrom(b.getClass()) == Comparable.class.isInstance(b)); -> це стосується і інтерфейсів.
Пуче

1
Технічність: Якщо objє, nullто clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)кине NullPointerExceptionі не повернеться true.
Ендрю Машерет

196

Обидві відповіді знаходяться в рейтингу, але жодна з них не є повною відповіддю.

MyClass.class.isInstance(obj)призначений для перевірки екземпляра. Він повертає істину, коли параметр obj не є нульовим і може бути переданий до MyClassбез підвищення a ClassCastException. Іншими словами, obj - це екземпляр MyClassабо його підкласи.

MyClass.class.isAssignableFrom(Other.class)повертає істину , якщо MyClassодне і те ж , як, або суперкласу або суперінтерфейс, Other. Otherможе бути класом або інтерфейсом. Він відповідає правді, якщо Otherйого можна перетворити на MyClass.

Невеликий код для демонстрації:

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
Чому у вашому прикладі "b isAssignableFrom a:", але код є A.class.isAssignableFrom(B.class)? Я заплутався у виході :)
Роман Труба

4
гммм ... у всіх ваших прикладах "instanceOf" повертає істинний iff, "isAssignableFrom" повертає true ... я не бачу різниці в цьому.
андроїд розробник

2
Будьте уважні, роздрукований текст не відповідає коду і може заплутати ... Приклад: "System.out.println (" b isAssignableFrom a: "+ A.class.isAssignableFrom (B.class));"
polster

21
@Paul Відповідь не є корисною, тому що читача залишається цікаво, "в чому різниця між об'єктом, що є екземпляром підкласу класу, і типом об'єкта, який може бути конвертованим у клас?" Звичайно, ви можете побачити, що ви залишили читача з такою ж кількістю запитань, прочитавши свою відповідь, як і він, коли зайшов на цю сторінку. Краща відповідь насправді пояснить різницю (або її відсутність). Якщо різниці немає, у відповіді має бути прямо зазначено, що "немає практичної різниці".
Олександр Дубінський

2
Що ще важливіше, читачеві залишається цікаво, що, до біса, використовувати їх цілі. Відповідно до коментарів у питанні, isAssignableFrom()викидає a, NullPointerExceptionякщо об’єкт є нульовим, тоді як isInstance()просто повертає false. Це справжня відповідь.
Андрій

6

Я думаю, що результат для цих двох має бути завжди однаковим. Різниця полягає в тому, що вам потрібен екземпляр класу, isInstanceа лише Classоб'єкт для використання isAssignableFrom.


Це не на 100% правда. Comparable.class.isAssignableFrom(Byte.class) == trueале Byte.class.isInstance(Comparable.class) == false. Іншими словами, isInstance()не є симетричним для інтерфейсів, лише для підкласів.
Гілі

6
@Gili: Ви там трохи помилилися. Byte.class.isInstance(Comparable.class)помилково, оскільки Classоб'єкт не є примірником Byte. Правильне порівняння Comparable.class.isAssignableFrom(Byte.class)IS Comparable.class.isInstance((byte) 1), що це правда.
ColinD

1
Я не погоджуюсь. Якщо ви подивитесь на Javadoc, Byteви виявите, що він розширюється Numberі є класом. (byte) 1не рівнозначно Byte. Перший - примітив. Останній - клас.
Гілі

2
@Gili: Autoboxing кидає примітивний byteдо , Byteтак як тип параметра isInstanceє Object.
ColinD

2
Добре. Моя первісна думка полягала в тому, що дзвінки не зовсім симетричні один одному, але перечитавши свою відповідь, ти ніколи не робив цього твердження, щоб ти мав рацію.
Гілі

6

Для стислості ми можемо зрозуміти ці два API, як нижче:

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

Якщо Xі Yє той самий клас, або Xце Yсуперклас або супер інтерфейс, поверніть true, інакше - false.

  1. X.class.isInstance(y)

Скажімо y, це екземпляр класу Y, якщо Xі Yтой самий клас, або XєY «s супер клас або супер інтерфейс, повертає істину, в іншому випадку, брехня.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.