Friends, thank you all for your help! Brainstorming really works, I was convinced of this on my own skin. I know that this topic introduces many novice programmers into a stupor, so I decided to paint my thoughts on this matter. I hope that you will not judge strictly.
So, let's start to understand this issue. What is the main problem of people (including mine) in understanding this topic? And the problem is that we confuse "priority" with the usual order of execution of statements. In what order does the JVM execute the instructions? Obviously, all instructions (as well as operators of compound expressions) are executed in the left-associative direction we are used to (from left to right), and when we reach the end of the line (as a rule, a special Unicode character is put at the end of each line (or their combination) line terminator (mainly characters that have the mnemonic designation CR + LF )), then we move to the lower line and execute the code from the very beginning in the same left-hand direction (you can think of it as a carriage return to the very beginning of the lines and in a typewriter, and then translation of the same carriage to the beginning of the next line).
When does the main difficulty begin? All troubles arise at all when we are faced with some uncertainty . What I mean? Let's look at a classic example of how to apply the operator priority table in practice. Take the following arithmetic expression:
/* * Some code */ int z = a + b * c;
From elementary school, we know that multiplicative operations are performed first, and then additive ones, since the former have a clear priority over the latter. How is this implemented in Java itself and what kind of collision can arise here? We see in the right part of the assignment operation a compound expression that consists of two binary arithmetic operators and 3 operands. Obviously, we have two possible paths that will intersect in one place. We can do this:
(a + b) * с;
Or so:
a + (b * c);
The collision is that in both cases we capture the variable b , which is also one of the operands relative to both operators. It is clear that the final result will differ depending on the chosen path. That's where the priorities of the operators come in! We know perfectly well that the multiplication operation will be performed first, because for us it is very obvious and we don’t even pay attention to it (although all this was originally written in the “brains” of the JVM itself).
And now I would like to turn to a more complex example, from which it all began. Why does the increment / decrement written in postfix notation take precedence over the prefix form of the same record? So I understood, then in both cases it is possible to give only by one example, where a clear uncertainty may arise. We give these examples:
a---b; a+++b;
This form of recording allows only 2 possible options without a compile-time error. Here you can select 2 operators, one of which will be a binary operator (addition or subtraction), as well as a unary increment / decrement (we don’t say anything about the form of the record). Here a slightly different kind of uncertainty arises, which differs from the first case we have considered. If in the first case there was a collision at the level of the shared operand, then there is an ambiguity in the question of the unary operator, which can be a postfix / prefix increment / decrement for both variable a and variable b . We have the following options for the disclosure of brackets:
(a--)-b; a-(--b); (a++)+b; a+(++b);
The position of the binary operator is of fundamental importance only in the first case, since the subtraction is anti-commutative operations, and addition, on the contrary, is commutative. I would like to add that this priority did not appear at all accidentally. To understand this, you need to contact JLS :
It is not necessary to make a program. There is one exception: If you follow the rules, it is one of the following exceptions: numerical comparison operator>.
A, A, A, A, A, A, A, A, A, B, A, B, A, B, A, B, A .
If you’re not a rule, you’ll be looking for a list of shift operator >>>. Worse, it can be ambiguous, for example, as a List , etc.
As we can understand, at each stage the longest broadcast is used, even if it leads to an incorrect program. Most likely it is for this reason that the postfix form of unary operators has some priority over the prefix one, this fits into the general logic of the lexical translation, especially other examples in which a collision could arise between such operators to come up with something that’s not that difficult, but most likely ( In any case, I personally do not see other possible options for writing the correct program, where I could simulate this situation).
Finally, we can consider an example with logical operators.
boolean bool = a ^ b & c | d; где a, b, c, d — переменные логического типа.
To understand which operation will be performed first, it would be nice to look here . Knowing the priority of each of the operators we find the right solution:
boolean bool = ((a ^ (b & c)) | d);
What I would like to say at the end? In the global network, you can find a lot of false tables that can be misleading. The authors add there any sort of gag, according to the type of separators, the operator new , operators of type casting and other nonsense. I believe that there is a single source to which you can refer in this matter, this is the official site of Oracle Corporation. And yes, I agree that it is better to use regular brackets to correct priorities! :) Thank you all for your attention! ;)