Sprawdź, czy obiekt implementuje interfejs


149

Prawdopodobnie zostało to zadane wcześniej, ale szybkie wyszukiwanie przyniosło tylko to samo pytanie zadane dla C #. Spójrz tutaj.

Zasadniczo chcę sprawdzić, czy dany obiekt implementuje dany interfejs.

W pewnym sensie wymyśliłem rozwiązanie, ale nie jest to po prostu wystarczająco wygodne, aby używać go często w instrukcjach if lub case i zastanawiałem się, czy Java nie ma wbudowanego rozwiązania.

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


EDYCJA: Ok, dziękuję za odpowiedzi. Specjalnie dla Damiena Polleta i Noldorina zmusiliście mnie do przemyślenia mojego projektu, więc nie testuję już interfejsów.


3
Czy nie możesz po prostu spróbować rzutowania i przechwycenia wyjątku, jeśli jeden zostanie wyrzucony (lub sprawdź, czy nie ma wyniku zerowego, nawet jeśli Java ma coś analogicznego do operatora „as” w języku C #)? Jestem raczej programistą C # niż Java, więc głównie zgaduję, chociaż sądzę, że takie podejście byłoby możliwe w każdym języku obiektowym.
Noldorin

1
Rzucanie wyjątków jest dobrą praktyką w tym przypadku tylko wtedy, gdy nie musisz przejmować się wydajnością.
Rafa

1
Przepraszam, ale gdzie te odpowiedzi sprawiły, że przemyślałeś swój projekt? Nawet jeśli usunęły, czym one były? Czy mógłbyś mi pomóc @sebastiangeiger
ozanmuyes

1
@ozanmuyes Przepraszam, nie pisałem Javy od ponad 4 lat i niestety nie pamiętam, co zrobiłem.
sebastiangeiger

Odpowiedzi:


191

instanceofOperator działa w NullPointerExceptionsposób bezpieczny. Na przykład:

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

daje prawdę. Od:

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

daje wartość false, instanceofoperator jest bezpieczny pod względem wartości null (przesłany kod nie jest).

instanceof to wbudowana, bezpieczna w czasie kompilacji alternatywa dla Class # isInstance (Object)


5
Jednak instanceof działa tylko na literałach klasowych. Nie można go więc użyć w przypadku OP
LordOfThePigs

oczywiście, jest bezpieczny w czasie kompilacji; i to jest sposób wbudowany i to jest argument pytania (imho)
dfa

@LordOfThePigs nie, nie ma. Sprawdza, czy zaimplementowano również interfejs.
NimChimpsky

5
@ NimChimpsky: źle zrozumiałeś mój punkt widzenia. Literały klasowe mają miejsce, gdy piszesz rzeczy takie jak MyClass.classlub MyInterface.classw kodzie źródłowym. Literały klas mogą odwoływać się do klas, interfejsów i typów pierwotnych i zwracają odpowiednią instancję klasy Class. Chodzi mi o to, że OP nie używa literału klasy, ale zamiast tego instancji klasy Class, i niestety operator instanceofsłowa kluczowego po prawej stronie musi być literałem klasy, a nie instancją klasy Class.
LordOfThePigs

@dsdsdsdsd Od tego posta nawet o nim nie słyszałem / nie czytałem, ale po sprawdzeniu w Google zorientowałem się, że jest to skrót od wyjątku zerowego wskaźnika.
ozanmuyes

42

To powinno wystarczyć:

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

Na przykład,

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

ocenia do true.


8

Wolę instanceof:

if (obj instanceof SomeType) { ... }

który jest znacznie bardziej powszechny i ​​czytelny niż SomeType.isInstance(obj)


5
Pamiętaj, że if (obj instanceof SomeType) { ... }jest statyczny (to znaczy - nie może się zmieniać w czasie wykonywania) i SomeType.isInstance(obj)jest dynamiczny.
Tomasz Bielaszewski


3

Jeśli chcesz przetestować interfejsy:

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 to interfejs, a myType to zdefiniowany przez Ciebie typ, który może implementować wiele interfejsów. Za pomocą tego kodu otrzymujesz tylko typy, które implementują zdefiniowany interfejs


1

Miałem dziś wieczorem ten problem z Androidem i po przyjrzeniu się rozwiązaniom javadoc wymyśliłem to prawdziwe działające rozwiązanie tylko dla osób takich jak ja, które potrzebują trochę więcej niż wyjaśnienia javadoc.

Oto działający przykład z rzeczywistym interfejsem korzystającym z języka Android java. Sprawdza działanie, które wywołało zaimplementowanie interfejsu AboutDialogListener przed próbą rzutowania pola 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;
        }
}

... Później sprawdzam, czy pole adl ma wartość! Null przed wywołaniem interfejsu

@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

Dzięki Apache commons-lang ArrayUtils możesz sprawdzić, czy wymagany interfejs jest zawarty w interfejsach obiektu

public static Boolean implementsInterface(Object object, Class interf){
    return ArrayUtils.contains(object.getClass().getInterfaces(), interf);
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.