Search code examples
javagenericsinstanceof

Java generics and the instanceof keyword


So, I was looking through the Oracle Java Tutorials, specifically this piece of code;

List<EvenNumber> le = new ArrayList<>();
List<? extends NaturalNumber> ln = le;
ln.add(new NaturalNumber(35));  // compile-time error

which can be found here. It is my understanding (and please correct me if I'm wrong) that the above code will not work because the compiler does not know that lnrefers to a List of EvenNumbers and so this prevents you from accidentally adding any object that could be a supertype of the elements that are meant for the List. IF that is the case, then why is it that if you have a statement like Number num = new Integer(6); the compiler is able to correctly determine that num is an Integer object if you write an if statement like so; if (num instanceof Integer) {...}?

I guess my question is, how is the compiler able to determine that num is referring to an Integer object in the second example, but not able to determine that ln is referring to a List<EvenNumber> object in the first example?


Solution

  • In general, the compiler is able to determine many things and it uses its observations when optimizing the code.

    However, Java is statically and strongly typed language and compiler has no freedom when it comes to type safety.

    1) Adding to the ln list is prohibited, because one does not know exactly which type of elements it is supposed to contain. In your example this rule prevented bringing the list to an invalid state.

    2) "...the compiler is able to correctly determine that num is an Integer..."

    Not true, the compiler must not determine it (although it could if Java were weakly typed language).

    3) num instanceof Integer

    This is evaluated at runtime, not at compile time. However, the following would produce the compile time error:

    num instanceof String

    because a Number can never be a String.