The grammar in chapter 18 of JLS v7 seem to differ from the constructs elsewhere in the documentation, but to me there seem to be differences. Specifically in chapter 15 the rules are:
RelationalExpression:
ShiftExpression
RelationalExpression < ShiftExpression
RelationalExpression > ShiftExpression
RelationalExpression <= ShiftExpression
RelationalExpression >= ShiftExpression
RelationalExpression instanceof ReferenceType
which makes foo instanceof Bar
a RelationalExpression (and therefore an EqualityExpresson) which in turn can be used as LHS in the EqualityExpression rule which makes foo instanceof Bar == false
an EqualityExpression.
But when looking at the grammar in chapter 18 they've simplified it a bit:
Expression2:
Expression3 [Expression2Rest]
Expression2Rest:
{ InfixOp Expression3 }
instanceof Type
Which looks odd, which means that we can chain together Expression3
s with binary operators OR we can check the type of one Expression3
. Specifically now foo instanceof Bar
is an Expression2
, but I don't see that it would be valid to use an Expression2
as LHS of an equality comparision.
Have I missed something in the grammar of chapter 18 that makes foo instanceof Bar == false
a valid expression? Note that it is a valid expression according to the rules in chapter 15 and according to my compiler.
This question deserves a good answer, so let's take a good close look.
Based solely on the grammar in Chapter 18:
Anything with an InfixOp (e.g. ==
) either fits Expression2Rest or fits nothing. And Expression2Rest only belongs inside Expression2. So, if foo instanceof Bar == false
is legal Java, that means that foo instanceof Bar
has to be an Expression3.
Expression2 :
Expression3 [Expression2Rest]Expression2Rest:
{InfixOp Expression3}
instanceof Type
But foo instanceof Bar
is not an Expression3. There's no PrefixOp and no cast, so to be an Expression3 it would have to be a Primary. But it just doesn't fit.
Expression3:
PrefixOp Expression3
( (Expression | Type) ) Expression3
Primary { Selector } { PostfixOp }Primary:
Literal
ParExpression
this [Arguments]
super SuperSuffix
new Creator
NonWildcardTypeArguments (ExplicitGenericInvocationSuffix | this Arguments)
Identifier { . Identifier } [IdentifierSuffix]
BasicType { [] }* .class
void.class
Conclusion: based solely on the grammar presented in Chapter 18, foo instanceof Bar == false
is not a legal Java expression. !?!?!
Of course that's nonsense. foo instanceof Bar
yields a boolean result, and that result can certainly be compared to false
. The expression compiles and runs.
Better conclusion: Chapter 18 isn't authoritative, but the rest of the book is.
Section 2.3 states that
A syntactic grammar for the Java programming language is given in Chapters 4, 6-10, 14, and 15. ... Chapter 18 also gives a syntactic grammar for the Java programming language, better suited to implementation than exposition.
By the grammar rules presented in Chapter 15, foo instanceof Bar == false
is a legal Java expression. But check out the last sentence before section 15.20.1: "The type of a relational expression is always boolean." That directly conflicts with the RelationalExpression rules themselves in 15.20. (In particular, it implies that the LHS of instanceof
must evaluate to boolean.) It can't possibly be true.
Bestest conclusion: This book has issues. If you want to know whether something is legal Java, you have to compile and run it, preferably on Oracle's reference implementation. And even then there might be bugs. It is, after all, just software.
And I think that if they changed the Expression2 rule just a little bit, Chapter 18 could be right. Like so:
*Expression2 :
Expression3 [ instanceof Type ]
Expression2 {InfixOp Expression3}
But who knows, that might cause other problems. In any case, it's fixed in Java 8.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With