My question in plain English: why this works someObject.methodReturnsInteger().getClass()
(I don't really mean the getClass
method. Just a method that works with Integer. And I don't really mean a method that returns an Integer specifically.) but this doesn't ++a++
?
In other words, why (or how) parsing (or tokenizing) allows using the return value in the first but doesn't in the second? I mean, shouldn't it parse the latter like so: (++a)++
and use the return of ++a
as a number?
The same goes for something like: a+++++b
I hope the question is clear enough.
Thank you for your time.
The expression ++a++
consists of 3 pieces, highlighted by adding parenthesis: (++(a))++
:
a
variables reference++X
Prefix Increment Operator (JLS §15.15.1)X++
Postfix Increment Operator (JLS §15.14.2)Javadoc says:
[X] must be a variable of a type that is convertible (§5.1.8) to a numeric type, or a compile-time error occurs. [...] The result of the [prefix/postfix] increment expression is not a variable, but a value.
So, in your expression ++a
works, because a
is a variable, but the result is a value, so (++a)++
doesn't work.
a+++++b
doesn't work because it is parsed by the compiler as ((a++)++)+b
, and as we just learned, X++
needs a variable.
It is parsed this way because the Java tokenizer will consume as many consecutive characters as possible to form a valid operator.
Now, if you add spaces or parenthesis, it can work, depending of what you intended that expression to do. The following are all the same:
(a++)+(++b)
a+++(++b)
a++ + ++b
a+++ ++b
The expression someObject.methodReturnsInteger().getClass()
is known as "method chaining".
This works because .
is a left-associative method invocation operator, and the value to the left of the .
just has to be an object (or class for static method call, but let's skip that).
So the expression is parsed like this:
( someObject . methodReturnsInteger() ) . getClass()
The first .
works because someObject
is an object. The second .
works because the result of the parenthesized expression is an object.
Method chaining is very common, and is very nice when using a builder pattern, e.g.
String s = new StringBuilder()
.append("Hello ")
.append(person.getFirstName())
.append(", please say hello to your father, ")
.append(person.getFather().getFirstName())
.append(".")
.toString();