Tester si l'objet implémente l'interface


149

Cela a probablement déjà été demandé, mais une recherche rapide n'a fait apparaître que la même question posée pour C #. Vois ici.

Ce que je veux essentiellement faire, c'est vérifier si un objet donné implémente une interface donnée.

J'ai en quelque sorte trouvé une solution, mais ce n'est tout simplement pas assez confortable pour l'utiliser fréquemment dans des déclarations if ou case et je me demandais si Java n'avait pas de solution intégrée.

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


EDIT: Ok, merci pour vos réponses. Surtout à Damien Pollet et Noldorin, vous m'avez fait repenser mon design pour ne plus tester d'interfaces.


3
Ne pouvez-vous pas simplement essayer de lancer et attraper l'exception si elle est lancée (ou vérifier un résultat nul même, si Java a quelque chose d'analogue à l'opérateur C # "as")? Je suis un codeur C # plutôt que Java, donc je ne fais que deviner ici, même si je pense qu'une telle approche serait possible dans n'importe quel langage OO.
Noldorin

1
Lancer une exception est une bonne pratique dans ce cas uniquement si vous n'avez pas à vous soucier des performances.
Rafa

1
Pardonnez-moi, mais où sont ces réponses qui vous ont fait repenser votre conception? Même s'ils ont été supprimés, quels étaient-ils? Pourriez-vous s'il vous plaît m'aider @sebastiangeiger
ozanmuyes

1
@ozanmuyes Je suis désolé, je n'ai pas écrit Java depuis plus de 4 ans et malheureusement je ne me souviens plus de ce que j'ai fait.
sebastiangeiger

Réponses:


191

L' instanceofopérateur effectue le travail de manière NullPointerExceptionsûre. Par exemple:

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

cède vrai. Puisque:

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

renvoie false, l' instanceofopérateur est null safe (le code que vous avez publié ne l'est pas).

instanceof est l'alternative intégrée et sécurisée à la compilation à Class # isInstance (Object)


5
Cependant, instanceof ne fonctionne que sur les littéraux de classe. Donc, il ne peut pas être utilisé dans le cas de l'OP
LordOfThePigs

bien sûr, il est sûr au moment de la compilation; et c'est la manière intégrée et c'est l'argument de la question (à mon humble avis)
dfa

@LordOfThePigs non, ce n'est pas le cas. Il vérifie si une interface est également implémentée.
NimChimpsky

5
@NimChimpsky: vous avez mal compris mon point. Les littéraux de classe sont lorsque vous écrivez des choses comme MyClass.classou MyInterface.classdans votre code source. Les littéraux de classe peuvent faire référence à des classes, des interfaces et des types primitifs, et renverront une instance correspondante de la classe Class. Mon point est que l'OP n'utilise pas un littéral de classe, mais une instance de la classe Class à la place, et malheureusement l'opérateur de droite du instanceofmot - clé doit être un littéral de classe, pas une instance de la classe Class.
LordOfThePigs

@dsdsdsdsd Depuis cet article, je n'ai même pas entendu / lu à ce sujet, mais après avoir cherché sur Google, j'ai compris qu'il s'agissait de l'abréviation de l'exception du pointeur nul.
ozanmuyes

42

Cela devrait faire:

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

Par exemple,

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

évalue à true.


8

Je préfère instanceof:

if (obj instanceof SomeType) { ... }

ce qui est beaucoup plus courant et lisible que SomeType.isInstance(obj)


5
N'oubliez pas que if (obj instanceof SomeType) { ... }c'est statique (c'est-à-dire qu'il ne peut pas changer au moment de l'exécution) et qu'il SomeType.isInstance(obj)est dynamique.
Tomasz Bielaszewski


3

Si vous souhaitez tester les interfaces:

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 est une interface et myType est un type que vous avez défini qui peut implémenter un certain nombre d'interfaces. Avec ce code, vous obtenez uniquement les types qui implémentent une interface définie


1

J'ai eu ce problème ce soir avec Android et après avoir regardé les solutions javadoc, j'ai trouvé cette vraie solution de travail juste pour les gens comme moi qui ont besoin d'un peu plus qu'une explication javadoc.

Voici un exemple de travail avec une interface réelle utilisant android java. Il vérifie l'activité qui a appelé à implémenter l'interface AboutDialogListener avant de tenter de convertir le champ 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;
        }
}

... Plus tard, je vérifie si le champ adl est! Null avant d'appeler l'interface

@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

Avec Apache commons-lang ArrayUtils, voyez si l'interface dont vous avez besoin est contenue dans les interfaces de votre objet

public static Boolean implementsInterface(Object object, Class interf){
    return ArrayUtils.contains(object.getClass().getInterfaces(), interf);
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.