Testen Sie, ob das Objekt die Schnittstelle implementiert

149

Dies wurde wahrscheinlich schon einmal gestellt, aber eine schnelle Suche brachte nur die gleiche Frage nach C #. Siehe hier.

Grundsätzlich möchte ich überprüfen, ob ein bestimmtes Objekt eine bestimmte Schnittstelle implementiert.

Ich habe eine Lösung gefunden, aber diese ist einfach nicht komfortabel genug, um sie häufig in if- oder case-Anweisungen zu verwenden, und ich habe mich gefragt, ob Java keine integrierte Lösung hat.

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


EDIT: Ok, danke für deine Antworten. Besonders für Damien Pollet und Noldorin haben Sie mich dazu gebracht, mein Design zu überdenken, damit ich nicht mehr auf Schnittstellen teste.

sebastiangeiger
quelle
3
Können Sie nicht einfach versuchen, die Ausnahme zu übertragen und abzufangen, wenn eine ausgelöst wird (oder nach einem Null-Ergebnis suchen, selbst wenn Java etwas Analoges zum C # "as" -Operator hat)? Ich bin eher ein C # -Codierer als ein Java-Codierer, daher rate ich hier hauptsächlich nur, obwohl ich denke, dass ein solcher Ansatz in jeder OO-Sprache möglich wäre.
Noldorin
1
Das Auslösen von Ausnahmen ist in diesem Fall nur dann empfehlenswert, wenn Sie sich nicht um die Leistung kümmern müssen.
Rafa
1
Verzeihung, aber wo sind diese Antworten, die Sie dazu gebracht haben, Ihr Design zu überdenken? Selbst wenn sie gelöscht wurden, was waren sie? Könnten Sie mir bitte helfen @sebastiangeiger
Ozanmuyes
1
@ozanmuyes Es tut mir leid, ich habe seit über 4 Jahren kein Java mehr geschrieben und kann mich leider nicht erinnern, was ich getan habe.
Sebastiangeiger

Antworten:

191

Der instanceofBediener erledigt die Arbeit auf NullPointerExceptionsichere Weise. Beispielsweise:

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

ergibt wahr. Schon seit:

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

ergibt false, der instanceofOperator ist null sicher (der von Ihnen gepostete Code ist nicht).

instanceof ist die integrierte, zur Kompilierungszeit sichere Alternative zu Class # isInstance (Object).

dfa
quelle
5
instanceof funktioniert jedoch nur mit Klassenliteralen. Es kann also nicht im Fall des OP verwendet werden
LordOfThePigs
Sicher, es ist zur Kompilierungszeit sicher. und es ist der eingebaute Weg und es ist das Argument der Frage (imho)
dfa
@ LordOfThePigs nein, tut es nicht. Es wird geprüft, ob auch eine Schnittstelle implementiert ist.
NimChimpsky
5
@NimChimpsky: Du hast meinen Standpunkt falsch verstanden. Klassenliterale sind, wenn Sie Dinge wie MyClass.classoder MyInterface.classin Ihren Quellcode schreiben . Klassenliterale können sich auf Klassen, Schnittstellen und primitive Typen beziehen und geben eine entsprechende Instanz der Klassenklasse zurück. Mein Punkt ist, dass das OP kein Klassenliteral verwendet, sondern stattdessen eine Instanz der Klassenklasse, und leider muss der Operator auf der rechten Seite des instanceofSchlüsselworts ein Klassenliteral sein, keine Instanz der Klassenklasse.
LordOfThePigs
@dsdsdsdsd Seit diesem Beitrag habe ich noch nicht einmal davon gehört / gelesen, aber nachdem ich bei Google nachgeschlagen habe, habe ich herausgefunden, dass es sich um eine Abkürzung für die Null-Zeiger-Ausnahme handelt.
Ozanmuyes
42

Dies sollte tun:

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

Beispielsweise,

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

bewertet zu true.

Luke Woodward
quelle
8

Ich bevorzuge instanceof:

if (obj instanceof SomeType) { ... }

Das ist viel häufiger und lesbarer als SomeType.isInstance(obj)

Steve Kuo
quelle
5
Denken Sie daran, dass dies if (obj instanceof SomeType) { ... }statisch ist (dh sich zur Laufzeit nicht ändern kann) und SomeType.isInstance(obj)dynamisch ist.
Tomasz Bielaszewski
4

das war einfach :

   interf.isInstance(object)
Andreas Petersson
quelle
3

Wenn Sie auf Schnittstellen testen möchten:

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 ist eine Schnittstelle und myType ist ein von Ihnen definierter Typ, der eine Reihe von Schnittstellen implementieren kann. Mit diesem Code erhalten Sie nur die Typen, die eine definierte Schnittstelle implementieren

Rafa
quelle
1

Ich hatte heute Abend dieses Problem mit Android und nachdem ich mir die Javadoc-Lösungen angesehen hatte, kam ich auf diese wirklich funktionierende Lösung, nur für Leute wie mich, die etwas mehr als eine Javadoc-Erklärung brauchen.

Hier ist ein funktionierendes Beispiel mit einer tatsächlichen Schnittstelle unter Verwendung von Android Java. Es überprüft die Aktivität, die die AboutDialogListener-Schnittstelle implementiert hat, bevor versucht wird, das AboutDialogListener-Feld umzuwandeln.

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;
        }
}

... Später überprüfe ich, ob das Feld adl! Null ist, bevor ich die Schnittstelle aufrufe

@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
quelle
0

Überprüfen Sie mit Apache commons-lang ArrayUtils, ob die gewünschte Schnittstelle in den Schnittstellen Ihres Objekts enthalten ist

public static Boolean implementsInterface(Object object, Class interf){
    return ArrayUtils.contains(object.getClass().getInterfaces(), interf);
}
ThePoltergeist
quelle