Probar si el objeto implementa la interfaz

149

Probablemente esto ya se haya preguntado antes, pero una búsqueda rápida solo generó la misma pregunta que se hizo para C #. Mira aquí.

Lo que básicamente quiero hacer es verificar si un objeto determinado implementa una interfaz determinada.

En cierto modo, descubrí una solución, pero esto no es lo suficientemente cómodo como para usarla con frecuencia en declaraciones if o case y me preguntaba si Java no tiene una solución incorporada.

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


EDITAR: Ok, gracias por tus respuestas. Especialmente para Damien Pollet y Noldorin, me hiciste repensar mi diseño para que ya no pruebe las interfaces.

sebastiangeiger
fuente
3
¿No puede intentar lanzar y capturar la excepción si se arroja uno (o verificar si hay un resultado nulo, incluso si Java tiene algo análogo al operador C # "como")? Soy un codificador de C # en lugar de Java, por lo que principalmente estoy adivinando aquí, aunque creo que este enfoque sería posible en cualquier lenguaje OO.
Noldorin
1
Lanzar una excepción es una buena práctica en este caso solo si no tiene que preocuparse por el rendimiento.
Rafa
1
Disculpe, pero ¿dónde están esas respuestas que le hicieron repensar su diseño? Incluso si se eliminaron, ¿qué eran? ¿Podría por favor ayudarme
@sebastiangeiger
1
@ozanmuyes Lo siento, no he escrito Java en más de 4 años y desafortunadamente no puedo recordar lo que hice.
sebastiangeiger

Respuestas:

191

El instanceofoperador hace el trabajo de NullPointerExceptionmanera segura. Por ejemplo:

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

rinde verdad. Ya que:

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

produce falso, el instanceofoperador es nulo seguro (el código que publicó no lo es).

instanceof es la alternativa segura incorporada en tiempo de compilación a Class # isInstance (Object)

dfa
fuente
55
Sin embargo, instanceof solo funciona en literales de clase. Por lo tanto, no se puede usar en el caso del OP
LordOfThePigs el
claro, es seguro en tiempo de compilación; y es la forma integrada y es el argumento de la pregunta (en mi humilde opinión)
dfa
@LordOfThePigs no, no lo hace. Comprueba si también se implementa una interfaz.
NimChimpsky
55
@NimChimpsky: no entendiste mi punto. Los literales de clase es cuando escribes cosas como MyClass.classo MyInterface.classen tu código fuente. Los literales de clase pueden referirse a clases, interfaces y tipos primitivos, y devolverán una instancia correspondiente a la clase Class. Mi punto es que el OP no está usando un literal de clase, sino una instancia de la clase Class, y desafortunadamente el operador del lado derecho de la instanceofpalabra clave debe ser un literal de clase, no una instancia de la clase Class.
LordOfThePigs
@dsdsdsdsd Desde esta publicación ni siquiera escuché / leí sobre ella, pero después de buscar en Google descubrí que es la abreviatura de la excepción de puntero nulo.
ozanmuyes
42

Esto debería hacer:

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

Por ejemplo,

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

evalúa a true.

Luke Woodward
fuente
8

Yo prefiero instanceof:

if (obj instanceof SomeType) { ... }

que es mucho más común y legible que SomeType.isInstance(obj)

Steve Kuo
fuente
55
Recuerde que if (obj instanceof SomeType) { ... }es estático (es decir, no puede cambiar en tiempo de ejecución) y SomeType.isInstance(obj)es dinámico.
Tomasz Bielaszewski
4

eso fue fácil :

   interf.isInstance(object)
Andreas Petersson
fuente
3

Si quieres probar 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 es una interfaz y myType es un tipo que definió que puede implementar varias interfaces. Con este código obtienes solo los tipos que implementan una interfaz definida

Rafa
fuente
1

Tuve este problema esta noche con Android y después de mirar las soluciones de javadoc se me ocurrió esta solución de trabajo real solo para personas como yo que necesitan un poco más que una explicación de javadoc.

Aquí hay un ejemplo de trabajo con una interfaz real que usa Android Java. Comprueba la actividad que llamó implementado la interfaz AboutDialogListener antes de intentar convertir el 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;
        }
}

... Más tarde compruebo si el campo adl es! Nulo antes de llamar a la interfaz

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

Con Apache commons-lang ArrayUtils, vea si la interfaz que necesita está contenida en las interfaces de su objeto

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