Para la interfaz dada IfA
con la clase de A
su aplicación y la clase B
que se extiende A
, me gustaría para determinar cuál de las dos clases A
y B
declara explícitamente que implementa la interfaz IfA
.
Obviamente IfA.class.isAssignableFrom(A.class)
, y IfA.class.isAssignableFrom(B.class)
son a la vez true
. Tenía la esperanza de un método como
B.class.declaresInterface(IfA.class)
-> false
A.class.declaresInterface(IfA.class)
-> true
Pero algo así no existe, ¿verdad?
Antecedentes: de alguna variable Class<? extends IfA> x
; sin saber si es A, B o alguna otra clase C que se extenderá A o B ... Me gustaría buscar la clase alta más estupenda que implementa la interfaz. Actualmente estoy implicando una búsqueda un poco feo para esto:
public class SomeTest {
@org.junit.Test
public void testIt() {
assertTrue(IfA.class.isAssignableFrom(A.class));
assertTrue(IfA.class.isAssignableFrom(B.class));
Class<? extends IfA> b = B.class;
Class<?> result = b;
// somewhat ugly search: from B.class find A.class
while (IfA.class.isAssignableFrom(result.getSuperclass())) {
result = result.getSuperclass();
}
Object s = result.getSuperclass();
assertSame(A.class, result);
assertFalse(IfA.class.isAssignableFrom(result.getSuperclass()));
}
interface IfA {
};
class A implements IfA {
};
class B extends A {
};
}
¿Hay una manera más explícita de la detección de la interfaz, lo que hace la búsqueda más fácil de entender?
Que yo sepa no hay ningún declaresInterface(...)
método en la misma a pesar de que podría haber una biblioteca que proporciona un JDK.
La Class
clase en sí proporciona el método una llamada getInterfaces()
que según el JavaDoc:
Devuelve los interfaces implementadas directamente por la clase o interfaz que representa este objeto.
Por lo tanto una implementación para boolean declaresInterface(Class<?> clazz, Class<?> interface )
debe ser bastante sencillo (aunque el rendimiento puede ser mejorado utilizando algún almacenamiento en caché):
boolean declaresInterface(Class<?> clazz, Class<?> iface) {
//note: you should add some checks, e.g. for null and correct types
return Arrays.stream( clazz.getInterfaces() )
.anyMatch( iface::equals );
}
pruebas:
//true because Integer implements Comparable<Integer>
declaresInterface( Integer.class, Comparable.class );
//false, because Integer extends Number and Number implements Serializable
declaresInterface( Integer.class, Serializable.class );