Проверьте, реализует ли объект интерфейс

149

Возможно, это уже задавалось ранее, но быстрый поиск поднял только тот же вопрос, который задавался для C #. Посмотреть здесь.

В основном я хочу проверить, реализует ли данный объект данный интерфейс.

Я вроде нашел решение, но это не достаточно удобно, чтобы использовать его часто в операторах if или case, и мне было интересно, не имеет ли Java встроенного решения.

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


РЕДАКТИРОВАТЬ: Хорошо, спасибо за ваши ответы. Особенно для Дэмиена Поллета и Нолдорина, вы заставили меня переосмыслить мой дизайн, чтобы я больше не тестировал интерфейсы.

sebastiangeiger
источник
3
Разве вы не можете просто попытаться привести и поймать исключение, если оно выброшено (или проверить нулевой результат, даже если в Java есть что-то аналогичное оператору C # «as»)? Я кодер на C #, а не на Java, так что я в основном только догадываюсь, хотя я думаю, что такой подход был бы возможен на любом ОО-языке.
Нолдорин
1
Бросать исключение - хорошая практика в этом случае, только если вам не нужно заботиться о производительности.
Рафа
1
Простите, но где эти ответы заставили вас переосмыслить свой дизайн? Даже если они удалили, что они были? Не могли бы вы помочь мне @sebastiangeiger
ozanmuyes
1
@ozanmuyes Извините, я не писал на Java более 4 лет и, к сожалению, не могу вспомнить, что я сделал.
Себастьянгеигер

Ответы:

191

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

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

дает истину. Поскольку:

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

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

instanceof - это встроенная безопасная альтернатива Class # isInstance (Object) во время компиляции

DFA
источник
5
instanceof работает только с литералами класса. Так что это не может быть использовано в случае ОП
LordOfThePigs
конечно, это безопасно во время компиляции; и это встроенный способ, и это аргумент вопроса (imho)
dfa
@LordOfThePigs нет, это не так. Он проверяет, реализован ли интерфейс, а также.
НимЧимпский
5
@NimChimpsky: вы не поняли мою точку зрения. Литералы класса - это когда вы пишете такие вещи, как MyClass.classили MyInterface.classв вашем исходном коде. Литералы класса могут ссылаться на классы, интерфейсы и примитивные типы и возвращать соответствующий экземпляр класса Class. Моя точка зрения заключается в том, что OP использует не литерал класса, а экземпляр класса, а, к сожалению, оператор правой части instanceofключевого слова должен быть литералом класса, а не экземпляром класса.
LordOfThePigs
@dsdsdsdsd С этого поста я даже не слышал и не читал об этом, но, посмотрев в Google, я понял, что это аббревиатура исключения Null Pointer.
ozanmuyes
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)динамическое.
Томаш Беляшевский
4

это было легко :

   interf.isInstance(object)
Андреас Петерссон
источник
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 - это определенный вами тип, который может реализовывать несколько интерфейсов. С помощью этого кода вы получаете только типы, которые реализуют определенный интерфейс

Rafa
источник
1

У меня была эта проблема сегодня вечером с android, и после просмотра решений 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());
    }
}
danny117
источник
0

С Apache commons-lang ArrayUtils посмотрите, содержится ли требуемый интерфейс в интерфейсах вашего объекта

public static Boolean implementsInterface(Object object, Class interf){
    return ArrayUtils.contains(object.getClass().getInterfaces(), interf);
}
ThePoltergeist
источник