How does instanceof work in Java, and what exactly does it test?
instanceof is a type test. It evaluates to true if the reference on the left is non-null and the object it points at is an instance of the type on the right, or of one of that type's subtypes. The reference itself is never dereferenced, so it is safe to use on a null reference — the result is simply false.
Three properties are worth stating precisely. First, it works on the runtime type, not the static type. If a variable is declared as Animal and holds a Dog, value instanceof Dog is true even though the compiler would not let you call a Dog method on the reference. Second, it returns false for null rather than throwing, which makes it the natural null check. Third, when the right-hand side is a type that the compiler can prove is impossible — for instance comparing against a final class that the object's type cannot be — the compiler may reject the comparison outright, turning a run-time failure into a build failure.
Its main use is guarding a downcast. The pattern if (value instanceof String) { String text = (String) value; ... } both narrows the type for the compiler and guarantees the cast will succeed, because the branch only runs when the test was true.
There is one subtlety about how the compiler handles the flow. Inside the if block the compiler knows the type has been narrowed, so the cast is redundant but harmless. Outside it, the compiler still sees the original type, which is why you cannot write the cast before the test. In modern Java the pattern matching form of instanceof removes that two-step dance entirely.