The
instanceof,
Class.isInstance()and
Class.isAssignableFrom() statements all aim at testing whether an object can be casted without triggering an exception.
public class Test { public static class A {}; public static class B extends A {}; public interface I {}; public static void main(String[] args) { A a = new A(); B b = new B(); // // instanceof // if ( B instanceof A ) {} // Illegal if ( B instanceof a ) {} // Illegal if ( b instanceof a ) {} // Illegal if ( b instanceof A ) {} // OK if ( b instanceof I ) {} // OK if ( null instanceof A ) {} // OK if ( b instanceof null ) {} // Illegal if ( b instanceof b.getClass() ) {} // Illegal if ( b instanceof double ) {} // Illegal if ( b instanceof Double ) {} // Illegal if ( b instanceof double.class ) {} // Illegal if ( b instanceof Double.class ) {} // Illegal // // isAssignableFrom() // // All OK if ( A.class.isAssignableFrom(B.class) ) {} if ( A.class.isAssignableFrom(b.getClass()) ) {} if ( a.getClass().isAssignableFrom(B.class) ) {} if ( a.getClass().isAssignableFrom(b.getClass()) ) {} // All OK if ( double.class.isAssignableFrom(double.class) ) {} if ( Double.class.isAssignableFrom(Double.class) ) {} if ( double.class.isAssignableFrom(B.class) ) {} if ( Double.class.isAssignableFrom(b.getClass()) ) {} // All OK if ( I.class.isAssignableFrom(double.class) ) {} if ( I.class.isAssignableFrom(Double.class) ) {} Class c = null; // Throws NullPointerException at runtime if ( A.class.isAssignableFrom(c) ) {} // // isInstance() // b = null; // All OK if ( A.class.isInstance(b) ) {} if ( a.getClass().isInstance(b) ) {} if ( double.class.isInstance(b) ) {} if ( Double.class.isInstance(b) ) {} if ( I.class.isInstance(b) ) {} // Throws NullPointerException at runtime if ( c.isInstance(a) ) {} } } About
instanceof:
- The left argument must be a reference to an object
- The right argument must be a class known at compile time
- The left argument cannot be a primitive
About
isAssignableFrom():
- The left argument must be a class (not necessarily known at compile time)
- The right argument must be a class (not necessarily known at compile time)
- The left argument can be a primitive
About
isInstance():
- The left argument must be a class (not necessarily known at compile time)
- The right argument must be a reference to an object (eventually null)
- The left argument cannot be null
Conclusion
- The isAssignableFrom() and isInstance() methods are more flexible than instanceof in that they do not require to know the right argument at compile time.
- The left argument of instanceof can be null, contrary to the isAssignableFrom() and isInstance() methods.
- The instanceof statement cannot be used with primitives.
- Only isInstance() can take a null right parameter without a generating compile time issue or throwing a NullPointerException at runtime.
- Only instanceof and isAssignableFrom() can be used to directly test interface implementation.
Therefore, the most stress-free solution to check whether an object (
null or not) can be cast without triggering an exception at runtime is
isInstance(). However, it cannot be used to check whether a
Class implements an
interface. In this case,
isAssignableFrom() remains the best solution.
Great article, helped me understand which way to use.
ReplyDeleteFound a cock-up:
ReplyDeleteAll three statements can be used to test interface implementation.
contradicts
Therefore, the most stress-free solution to check whether an object (null or not) can be cast without triggering an exception at runtime is isInstance().
However, it cannot be used to check whether a Class implements an interface. In this case, isAssignableFrom() remains the best solution.
Nice and clear article nevertheless
Thanks, I have updated the post. isInstance() cannot be used to directly check whether a class implements an interface.
Delete