The <code>instanceof</code> Operator in Java

instanceof is a binary operator that returns true if its left-hand reference points to an object that is an instance of the right-hand type (or a subtype). It's a runtime check β€” so it sees the actual class of the object, not the declared type of the variable.

Classic form

Object o = "hello";
if (o instanceof String) {
    String s = (String) o;              // cast after the check
    System.out.println(s.length());
}

Pattern matching (Java 16+)

if (o instanceof String s) {             // declares `s`, only in scope where true
    System.out.println(s.length());
}

The binding variable is implicitly final and only visible in the true branch (and in expressions logically guarded by the test).

Null safety

String s = null;
s instanceof String;                     // false β€” always. No NullPointerException.

Subtype relationship

Object o = new ArrayList<>();
o instanceof List;           // true  β€” ArrayList implements List
o instanceof Collection;     // true  β€” List extends Collection
o instanceof String;         // false

Generics and instanceof

Due to type erasure, you can't check a parameterised type at runtime:

if (x instanceof List<String>)          // ❌ compile error
if (x instanceof List<?> list)          // βœ… wildcard is fine

When instanceof is a smell

If your code is a ladder of instanceof checks on one hierarchy, consider polymorphism β€” a virtual method on the base type is usually cleaner. Pattern matching for switch (Java 21+) makes the remaining legitimate cases concise.

Common mistakes

  • Casting without checking β€” (String) o throws ClassCastException at runtime.
  • Forgetting null β€” an extra null-check before instanceof is redundant; null instanceof X is always false.
  • Using getClass() when you want instanceof β€” getClass() == X.class doesn't match subclasses.

Related

Pillar: Java operators. See also instanceof keyword, ClassCastException.