Перевірте, чи об'єкт реалізує інтерфейс


149

Про це, мабуть, питали і раніше, але швидкий пошук підняв лише те саме запитання, що і для C #. Дивіться тут.

Що я в основному хочу зробити, це перевірити, чи даний об'єкт реалізує даний інтерфейс.

Я начебто розібрався з рішенням, але це просто недостатньо зручно для його частого використання в заявах або випадках, і мені було цікаво, якщо Java не має вбудованого рішення.

public static Boolean implementsInterface(Object object, Class interf){
    for (Class c : object.getClass().getInterfaces()) {
        if (c.equals(interf)) {
            return true;
        }
    }
    return false;
}


РЕДАКТ: Добре, дякую за відповіді. Особливо для Демієна Поллета та Нолдоріна, ти змусив мене переосмислити свій дизайн, тому я більше не тестую на інтерфейси.


3
Чи не можете ви просто спробувати кастинг і зловити виняток, якщо викинуте його (або перевірте, чи немає нульового результату, навіть якщо Java має щось аналогічне оператору C # "як")? Я кодер C #, а не Java, тому я тут головним чином лише здогадуюсь, хоча я думаю, що такий підхід можливий у будь-якій мові ОО.
Нолдорін

1
Викидання винятків є гарною практикою в цьому випадку, лише якщо вам не потрібно піклуватися про продуктивність.
Рафа

1
Вибачте, але де саме ці відповіді змусили вас переосмислити свій дизайн? Навіть якщо вони видаляли, що це було? Чи можете ви мені допомогти @sebastiangeiger
ozanmuyes

1
@ozanmuyes Вибачте, я не писав Java більше 4 років і, на жаль, не можу згадати, що я робив.
sebastiangeiger

Відповіді:


191

instanceofОператор робить роботу в NullPointerExceptionбезпечному способі. Наприклад:

 if ("" instanceof java.io.Serializable) {
     // it's true
 }

вдається. З моменту:

 if (null instanceof AnyType) {
     // never reached
 }

дає хибність, instanceofоператор захищений від нуля (код, який ви опублікували, немає).

instanceof - це вбудована безпечна для компіляції час альтернатива класу # isInstance (Object)


5
instanceof, однак, працює лише на класових літералах. Тому його не можна використовувати у випадку з ОП
LordOfThePigs

звичайно, це безпечно для компіляції; і це вбудований спосіб, і це аргумент питання (imho)
dfa

@LordOfThePigs ні, це не так. Він перевіряє, чи інтерфейс реалізований також.
NimChimpsky

5
@NimChimpsky: ти неправильно зрозумів мою думку. Буквене позначення класу - це коли ви пишете такі речі, як у MyClass.classабо MyInterface.classвихідний код. Дослідники класів можуть посилатися на класи, інтерфейси та примітивні типи і повертатимуть відповідний екземпляр класу Class. Моя думка полягає в тому, що ОП - це не використання буквального класу, а екземпляр класу, а, на жаль, оператор правого боку цього instanceofключового слова повинен бути буквальним класом, а не екземпляром класу.
LordOfThePigs

@dsdsdsdsd З цього повідомлення я навіть не чув / не читав про нього, але, переглянувши Google, я зрозумів, що це абревіатура Null Pointer Exception.
озанмуї

42

Це слід зробити:

public static boolean implementsInterface(Object object, Class interf){
    return interf.isInstance(object);
}

Наприклад,

 java.io.Serializable.class.isInstance("a test string")

оцінює до true.


8

Я віддаю перевагу instanceof:

if (obj instanceof SomeType) { ... }

що набагато частіше і читабельніше, ніж SomeType.isInstance(obj)


5
Пам'ятайте, що if (obj instanceof SomeType) { ... }це статично (тобто не може змінюватися під час виконання) і SomeType.isInstance(obj)є динамічним.
Томаш Білашевський


3

Якщо ви хочете протестувати інтерфейси:

public List<myType> getElement(Class<?> clazz) {
    List<myType> els = new ArrayList<myType>();
    for (myType e: this.elements.values()) {
        if (clazz.isAssignableFrom(e.getClass())) {
            els.add(e);
        }
    }
    return els;

}

clazz - це інтерфейс, а myType - тип, визначений вами, який може реалізувати ряд інтерфейсів. За допомогою цього коду ви отримуєте лише типи, які реалізують визначений інтерфейс


1

У мене сьогодні була проблема з андроїдом, і переглянувши рішення javadoc, я придумав це справжнє робоче рішення саме для таких людей, як я, яким потрібно трохи більше, ніж пояснення javadoc.

Ось робочий приклад із фактичним інтерфейсом за допомогою Android java. Він перевіряє активність, яка викликала реалізований інтерфейс AboutDialogListener, перш ніж намагатися передати поле AboutDialogListener.

public class About extends DialogFragment implements OnClickListener,
    OnCheckedChangeListener {

public static final String FIRST_RUN_ABOUT = "com.gosylvester.bestrides.firstrunabout";


public interface AboutDialogListener {
    void onFinishEditDialog(Boolean _Checked);
}

private AboutDialogListener adl;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Activity a = this.getActivity();
    if (AboutDialogListener.class.isInstance(a)) {
        adl = (AboutDialogListener) a;
        }
}

... Пізніше я перевіряю, чи є поле adl! Null перед тим, як викликати інтерфейс

@Override
public void onStop() {
    super.onStop();
    sharedPref.edit().putBoolean(About.FIRST_RUN_ABOUT, _Checked).commit();
    // if there is an interface call it.
    if (adl != null) {
        adl.onFinishEditDialog(is_Checked());
    }
}

0

За допомогою Apache commons-lang ArrayUtils подивіться, чи потрібний потрібний інтерфейс в інтерфейсах вашого об'єкта

public static Boolean implementsInterface(Object object, Class interf){
    return ArrayUtils.contains(object.getClass().getInterfaces(), interf);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.