I've been under the impression that in Java, the instanceof operator cannot be used with generics due to type erasure. However, the first conditional statement in my code snippet below compiles and runs without any errors. Can anyone shed light on why the first conditional doesn't cause a compile-time error? I'm using IntelliJ IDEA with Oracle JDK 17.
public class InstanceofTest {
public static class Tea {}
public static class Herb {}
// Why is this working?
public static void main(String[] args) {
List<Tea> teas = new ArrayList<>();
if (teas instanceof List<Tea>) {
System.out.println("TRUE");
} else {
System.out.println("FALSE");
}
// Compile error
// if (teas instanceof List<Herb>) {
// System.out.println("TRUE");
// } else {
// System.out.println("FALSE");
// }
}
}
In Java, generics like
List<Tea>, are reduced to justListwhen your code runs, that's why you generally can't useinstanceofwith a generic type. The reasoninstanceof List<Tea>works is because, at compile time, the Java compiler is only checking against theListpart ofList<Tea>. It doesn't care about the<Tea>part because of type erasure, but it doesn't throw an error since it's not wrong to write it that way, and the syntax itself isn't inccorrect. The compiler is aware that you're dealing with aList<Tea>from the context, so it won't object.On the other hand, when you try
instanceof List<Herb>, the compiler steps in because it knows your list can't be aList<Herb>, since you told it it was aList<Tea>. This happens at compile time, based on the information you've provided, regardless of the list's actual content at runtime.TL;DR:
Java compiler makes decisions based on the information available at compile time, not on the actual contents of the list during runtime, due to type erasure.