Class#isAssignableFrom(…)
Despite Java’s age, there are a few hidden methods that sometimes escape developer attention. One of these is Class#isAssignableFrom(Class). It’s understandable if you’ve reviewed this method and your eyes glazed over at the documentation - it’s horrible:
Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter. It returns true if so; otherwise it returns false. If this Class object represents a primitive type, this method returns true if the specified Class parameter is exactly this Class object; otherwise it returns false.
Specifically, this method tests whether the type represented by the specified Class parameter can be converted to the type represented by this Class object via an identity conversion or via a widening reference conversion. See The Java Language Specification, sections 5.1.1 and 5.1.4 , for details.
That’s a long was of saying that calling this method on a subclass or implementing interface returns true. Otherwise it returns false. Here’s some example code you can compile and run to get a clear explanation:
import java.util.*;
public class AssignableTest {
public static void main(String[] argv) {
ArrayList implementation = new ArrayList();
Class interfaceClass = java.util.List.class;
System.out.println(interfaceClass.isAssignableFrom(implementation.getClass()));
System.out.println(implementation.getClass().isAssignableFrom(interfaceClass));
}
}
So it’s clever, but when is this method useful? If you’re using something like Hibernate that deals with CGLIB proxies, class equality can break. CGLIB proxies are subclasses of your object, so code like:
if (myInstance.getClass() == MyDomainObject.class) {
//...
}
doesn’t work if ‘myInstance’ is actually an instance of a CGLIB proxy, rather than your persistent object. Instead, isAssignableFrom(Class) works as expected:
if (MyDomainObject.class.isAssignableFrom(myInstance.getClass())) {
//...
}
Granted, it’s not useful very often, but it can avoid some ugly reflection hacks if you didn’t know it existed.