So, any instance of B is also an instance of A, and any instance of D is also an instance of A, and any instance of C is also an instance of B, and any instance of C is also an instance of A.
According to the Java Language Specification, "the result of the instanceof operator is true if the value of the ... [first operand, which must be a reference] is not null and the reference could be cast (�15.16) to the ... [second operand, which must be a type] without raising a ClassCastException. Otherwise the result is false." (The bold is mine.)
"a1 = new D()" creates a new instance of type D, and assigns it to a variable of type A (an upcast). So, "(a1 = new D()) instanceof C" returns false, because the true runtime type of a1 is D, and an instance of D is not an instance of C. In particular, a reference to an instance of D cannot be cast to type C without a ClassCastException.
Now, here's the trick: Because this evaluates to false, the second boolean is not evaluated due to short-circuiting of the && operator. In particular, "a2 = new B()" does not execute, and a2 remains a null reference. Therefore, "a2 instance of B" actually returns false.
"We're kind of on the level of crossword puzzle writers... And no one ever goes to them and gives them an award." ~Joe Strummer sscce.org
Joined: Sep 19, 2004
There are situations where you have a general type and need something more specific. Consider a method that counts ten-speed bikes but it gets a list containing all different makes and models.
There is no "type" attribute in Bike so you are stuck testing the type using instanceof. Any TenSpeed or any bike that inherits TenSpeed will be counted. If a Buzzard inherits from Bird then Buzzard IS-A bird.