Ответ 1
Сначала разделите это на три отдельных случая, которые не могут взаимодействовать:
int i = 1;
System.out.println(i+ + +i); // 2
int j = 1;
System.out.println(j++ +j); // 3
int k = 1;
System.out.println(k+++k); // 3
Теперь перепишем их с помощью скобок:
int i = 1;
System.out.println(i + (+(+i)));
int j = 1;
System.out.println((j++) + j);
int k = 1;
System.out.println((k++) + k);
Первая операция
Здесь мы не можем использовать операторы префикса или постфикса ++, поскольку у нас нет знака ++
в любом месте. Вместо этого у нас есть двоичный + оператор и два унарных + оператора.
Вторая операция
Это просто: это в значительной степени, как он читает, оператор postfix ++, за которым следует двоичный + оператор (а не унарный оператор +, который в противном случае подразумевает +j
).
Третья операция
Окончательная строка анализируется как (k++) + k
, а не k + (++k)
. В этой ситуации оба варианта будут давать одинаковый ответ, но мы можем доказать, что именно с помощью двух разных переменных:
int k1 = 1;
int k2 = 1;
System.out.println(k1+++k2); // Prints 2
System.out.println(k1); // Prints 2
System.out.println(k2); // Prints 1
Как вы можете видеть, он k1
был увеличен, а не k2
.
Причина, по которой k+++k
анализируется как токены k
, ++
, +
, k
обусловлена частью 3.2 JLS, который включает в себя:
Самый длинный возможный перевод используется на каждом шаге, даже если результат в конечном итоге не делает правильную программу, в то время как другой лексический перевод будет.
Четвертая операция (сбой компиляции)
То же самое правило "максимально длинного перевода" анализирует i++++i
как i
, ++
, ++
, i
, которое не является допустимым выражением (поскольку результат операции ++
значение, а не переменная).