Java: Class.isInstance против Class.isAssignableFrom


232

Позвольте clazzбыть некоторыми Classи objбыть некоторыми Object.

Является

clazz.isAssignableFrom(obj.getClass())

всегда так же, как

clazz.isInstance(obj)

?

Если нет, в чем различия?


26
если obj == null, второе возвращает false, первое - нет. ;)
Питер Лоури

21
@PeterLawrey, первый бросит, NullPointerExceptionесли obj == null.
ryvantage

Нашел какой-то ответ с образцами из hrere: mytechnotes.biz/2012/07/…
Парамеш Корракути

4
Читателям: вы собираетесь войти в глубокую, темную, черную дыру, из которой вы никогда не выйдете. Различия бесконечны.
Эндрю

@ParameshKorrakuti имя домена меняется на tshikatshikaaa.blogspot.com/2012/07/…
Жером Верстринж

Ответы:


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) имеет значение true. Где я сказал иначе?
Uckelman

5
@Gili Это не то, что сказал Укельман. Пожалуйста, перечитайте его ответ.
Puce

2
Byte b = 3; Comparable.class.isAssignableFrom(b.getClass()) == Comparable.class.isInstance(b)); -> Это верно и для интерфейсов.
Puce

1
Техническость: если objесть, nullто clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)брошу NullPointerExceptionи не вернусь true.
Эндрю Мачерет

196

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

MyClass.class.isInstance(obj)для проверки экземпляра. Он возвращает true, когда параметр obj не равен NULL и может быть приведен к MyClassбез повышения a 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();
    }

    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" возвращает истину, если "isAssignableFrom" возвращает истину ... Я не вижу разницы в этом пути.
Android-разработчик

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
@ Гили: у вас там немного не так. 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)

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.