Verifica se l'oggetto implementa l'interfaccia


149

Probabilmente questo è stato chiesto prima, ma una rapida ricerca ha sollevato solo la stessa domanda posta per C #. Vedere qui.

Quello che sostanzialmente voglio fare è controllare se un determinato oggetto implementa una determinata interfaccia.

Ho trovato una soluzione, ma questo non è abbastanza comodo da usarla frequentemente in if o case case e mi chiedevo se Java non avesse una soluzione integrata.

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


EDIT: Ok, grazie per le tue risposte. Soprattutto con Damien Pollet e Noldorin, mi hai fatto ripensare il mio progetto in modo da non testare più le interfacce.


3
Non puoi semplicemente provare a trasmettere e catturare l'eccezione se ne viene lanciata una (o controllare anche se il risultato è nullo, se Java ha qualcosa di analogo all'operatore C # "as")? Sono un programmatore C # piuttosto che Java, quindi sto solo indovinando qui, anche se penso che un tale approccio sarebbe possibile in qualsiasi linguaggio OO.
Noldorin,

1
Generare eccezioni è una buona pratica in questo caso solo se non devi preoccuparti delle prestazioni.
Rafa,

1
Scusami ma dove sono state quelle risposte che ti hanno fatto ripensare il tuo design? Anche se cancellati, che cosa erano? Potresti per favore aiutarmi @sebastiangeiger
ozanmuyes,

1
@ozanmuyes Mi dispiace, non scrivo Java da oltre 4 anni e sfortunatamente non ricordo cosa ho fatto.
sebastiangeiger,

Risposte:


191

L' instanceofoperatore esegue il lavoro in NullPointerExceptionmodo sicuro. Per esempio:

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

cede vero. Da:

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

restituisce false, l' instanceofoperatore è nullo e sicuro (il codice che hai pubblicato non lo è).

instanceof è l'alternativa sicura integrata in fase di compilazione a Class # isInstance (Object)


5
instanceof funziona solo su letterali di classe. Quindi non può essere utilizzato nel caso del PO
LordOfThePigs,

certo, è sicuro durante la compilazione; ed è il modo integrato ed è l'argomento della domanda (imho)
dfa

@LordOfThePigs no, non è così. Verifica se anche un'interfaccia è implementata.
NimChimpsky,

5
@NimChimpsky: hai frainteso il mio punto. I letterali di classe sono quando scrivi cose come MyClass.classo MyInterface.classnel tuo codice sorgente. I letterali di classe possono fare riferimento a classi, interfacce e tipi primitivi e restituiranno un'istanza corrispondente alla classe Class. Il mio punto è che l'OP non utilizza un valore letterale di classe, ma un'istanza della classe Class, e sfortunatamente l'operatore di destra della instanceofparola chiave deve essere un valore letterale di classe, non un'istanza della classe Class.
LordOfThePigs

@dsdsdsdsd Da questo post non ne ho nemmeno sentito / letto, ma dopo aver cercato su Google ho capito che è l'abbreviazione di Null Pointer Exception.
ozanmuyes,

42

Questo dovrebbe fare:

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

Per esempio,

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

valuta true.


8

Io preferisco instanceof:

if (obj instanceof SomeType) { ... }

che è molto più comune e leggibile di SomeType.isInstance(obj)


5
Ricorda che if (obj instanceof SomeType) { ... }è statico (cioè - non può cambiare in fase di esecuzione) ed SomeType.isInstance(obj)è dinamico.
Tomasz Bielaszewski,


3

Se si desidera verificare le interfacce:

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 è un'interfaccia e myType è un tipo che hai definito che può implementare una serie di interfacce. Con questo codice ottieni solo i tipi che implementano un'interfaccia definita


1

Stasera ho avuto questo problema con Android e dopo aver esaminato le soluzioni javadoc ho trovato questa vera soluzione funzionante solo per persone come me che hanno bisogno di qualcosa di più di una spiegazione javadoc.

Ecco un esempio funzionante con un'interfaccia reale che utilizza Android Java. Controlla l'attività che ha chiamato implementato l'interfaccia AboutDialogListener prima di tentare di trasmettere il campo 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;
        }
}

... Successivamente controllo se il campo adl è! Null prima di chiamare l'interfaccia

@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

Con ArrayUtils commons-lang di Apache, verifica se l'interfaccia richiesta è contenuta nelle interfacce dell'oggetto

public static Boolean implementsInterface(Object object, Class interf){
    return ArrayUtils.contains(object.getClass().getInterfaces(), interf);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.