Class.isInstance срещу Class.isAssignableFrom

1. Въведение

В този бърз урок ще разгледаме разликата между Class.isInstance и Class.isAssignableFrom . Ще научим как да използваме всеки метод и какви са разликите между тях.

2. Настройка

Нека настроим интерфейс и няколко класа, които да използваме, докато изследваме функционалностите Class.isInstance и Class.isAssignableFrom .

Първо, нека дефинираме интерфейс:

public interface Shape { }

След това нека дефинираме клас, който реализира Shape :

public class Triangle implements Shape { }

Сега ще създадем клас, който разширява Triangle :

public class IsoscelesTriangle extends Triangle { }

3. Class.isInstance

Методът isInstance за класа Class е еквивалентен на оператора instanceof . Методът isInstance е въведен в Java 1.1, защото може да се използва динамично. Този метод ще върне вярно, ако аргументът не е нулев и може успешно да бъде прехвърлен към референтния тип, без да се повишава ClassCastException .

Нека да разгледаме как можем да използваме метода isInstance с дефинирания от нас интерфейс и класове:

@Test public void whenUsingIsInstanceProperly_desiredResultsHappen() { Shape shape = new Triangle(); Triangle triangle = new Triangle(); IsoscelesTriangle isoscelesTriangle = new IsoscelesTriangle(); Triangle isoscelesTriangle2 = new IsoscelesTriangle(); Shape nonspecificShape = null; assertTrue(Shape.class.isInstance(shape)); assertTrue(Shape.class.isInstance(triangle)); assertTrue(Shape.class.isInstance(isoscelesTriangle)); assertTrue(Shape.class.isInstance(isoscelesTriangle2)); assertFalse(Shape.class.isInstance(nonspecificShape)); assertTrue(Triangle.class.isInstance(shape)); assertTrue(Triangle.class.isInstance(triangle)); assertTrue(Triangle.class.isInstance(isoscelesTriangle)); assertTrue(Triangle.class.isInstance(isoscelesTriangle2)); assertFalse(IsoscelesTriangle.class.isInstance(shape)); assertFalse(IsoscelesTriangle.class.isInstance(triangle)); assertTrue(IsoscelesTriangle.class.isInstance(isoscelesTriangle)); assertTrue(IsoscelesTriangle.class.isInstance(isoscelesTriangle2)); }

Както виждаме, дясната страна може да бъде еквивалентна или по-конкретна от лявата страна . Предоставянето на null на метода isInstance връща false .

4. Class.isAssignableFrom

Методът Class.isAssignableFrom ще върне вярно, ако Класът от лявата страна на израза е същият или е суперклас или суперинтерфейс на предоставения параметър Клас .

Нека използваме нашите класове с метода isAssignableFrom :

@Test public void whenUsingIsAssignableFromProperly_desiredResultsHappen() { Shape shape = new Triangle(); Triangle triangle = new Triangle(); IsoscelesTriangle isoscelesTriangle = new IsoscelesTriangle(); Triangle isoscelesTriangle2 = new IsoscelesTriangle(); assertFalse(shape.getClass().isAssignableFrom(Shape.class)); assertTrue(shape.getClass().isAssignableFrom(shape.getClass())); assertTrue(shape.getClass().isAssignableFrom(triangle.getClass())); assertTrue(shape.getClass().isAssignableFrom(isoscelesTriangle.getClass())); assertTrue(shape.getClass().isAssignableFrom(isoscelesTriangle2.getClass())); assertFalse(triangle.getClass().isAssignableFrom(Shape.class)); assertTrue(triangle.getClass().isAssignableFrom(shape.getClass())); assertTrue(triangle.getClass().isAssignableFrom(triangle.getClass())); assertTrue(triangle.getClass().isAssignableFrom(isoscelesTriangle.getClass())); assertTrue(triangle.getClass().isAssignableFrom(isoscelesTriangle2.getClass())); assertFalse(isoscelesTriangle.getClass().isAssignableFrom(Shape.class)); assertFalse(isoscelesTriangle.getClass().isAssignableFrom(shape.getClass())); assertFalse(isoscelesTriangle.getClass().isAssignableFrom(triangle.getClass())); assertTrue(isoscelesTriangle.getClass().isAssignableFrom(isoscelesTriangle.getClass())); assertTrue(isoscelesTriangle.getClass().isAssignableFrom(isoscelesTriangle2.getClass())); assertFalse(isoscelesTriangle2.getClass().isAssignableFrom(Shape.class)); assertFalse(isoscelesTriangle2.getClass().isAssignableFrom(shape.getClass())); assertFalse(isoscelesTriangle2.getClass().isAssignableFrom(triangle.getClass())); assertTrue(isoscelesTriangle2.getClass().isAssignableFrom(isoscelesTriangle.getClass())); assertTrue(isoscelesTriangle2.getClass().isAssignableFrom(isoscelesTriangle2.getClass())); }

Както при примера isInstance , можем ясно да видим, че дясната страна трябва да бъде или същата, или по-специфична от лявата страна. Също така можем да видим, че никога не можем да присвоим нашия интерфейс Shape .

5. Разликите

След като изложихме няколко подробни примера, нека разгледаме някои от разликите:

  1. За да използваме isInstance , трябва да знаем какъв е един от класовете по време на компилация.
  2. Само isAssignableFrom може да се използва с примитиви. Трябва да се отбележи, че ако използваме примитиви, методът само ще се върне вярно , ако Class обект и клас параметър са абсолютно същия клас .
  3. В isAssignableFrom методът ще хвърлят NullPointerException ако обектът използват от двете страни на експресията е нула . Ако предоставите null на метода isInstance , той ще върне false .
  4. Трябва да мислим за isInstance като отговор на въпроса дали предоставеният обект е от типа, с който го сравняваме (директно или чрез интерфейс или наследяване). Можем да помислим за isAssignableFrom като отговор на въпроса дали можем да определим параметричния клас като обектния клас. С други думи, триъгълникът Triangle = new IsoscelesTriange () ще се компилира ли?

6. Заключение

В този кратък урок разгледахме методите Class.isInstance и Class.isAssignableFrom и разгледахме тяхното използване и как се различават.

Както винаги, примерният код за този урок може да бъде намерен в GitHub.