Find out if a Class explicitly declares implementing a particular interface

Selaron :

For the given Interface IfA with class A implementing it and class B extending A, I'd like to determine which of both classes A and B explicitly declare implementing the interface IfA.

Obviously IfA.class.isAssignableFrom(A.class) and IfA.class.isAssignableFrom(B.class) are both true. I hoped for a Method like

B.class.declaresInterface(IfA.class) -> false

A.class.declaresInterface(IfA.class) -> true

But something like this does not exist, does it?


Background: from some variable Class<? extends IfA> x; not knowing if it is A, B or some other class C extending A or B ... I'd like to search the upper most super class implementing the interface. Currently I'm implying a somewhat ugly search for this:

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

Is there a more explicity way of interface detection, making the search easier to understand?

Thomas :

Afaik there's no declaresInterface(...) method in the JDK itself although there might be a library that provides one.

The Class class itself provides the a method called getInterfaces() which according to the JavaDoc:

Returns the interfaces directly implemented by the class or interface represented by this object.

Thus an implementation for boolean declaresInterface(Class<?> clazz, Class<?> interface ) should be quite straight forward (though performance might be improved using some caching):

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

Tests:

//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 ); 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=128859&siteId=1