Search code examples
javaprefixunary-operatorpostfix-operator

Unary-Operators postfix and prefix at the same time in java


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.


Solution

  • The expression ++a++ consists of 3 pieces, highlighted by adding parenthesis: (++(a))++:

    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();