class Test {
int a;
void method() {
a = 1;
int a = a = 2;
a = 3;
}
}
В a много method. Что они все имеют в виду?




Это простой пример причудливости правил области видимости Java.
a = 1;
int a = a = 2;
a = 3;
Построчно:
a = 1; относится к переменной-члену.a = 3; ссылается на локальную переменную, потому что он находится после объявления локальной переменной. Довольно сбивает с толку то, что вы можете ссылаться на два разных символа через один и тот же идентификатор одним и тем же методом.int a = a = 2;: второй a - это локальная переменная.Ссылка на себя в объявлении переменной действительно любопытна. Вы можете найти этот в спецификации языка:
- The scope of a local variable declaration in a block (§14.4) is the rest of the block in which the declaration appears, starting with its own initializer and including any further declarators to the right in the local variable declaration statement.
Верно также и то, что переменные-члены могут ссылаться на себя в собственном инициализаторе; но это по несколько другой причине:
- The scope of a declaration of a member m declared in or inherited by a class type C (§8.1.6) is the entire body of C, including any nested type declarations.
Мне еще предстоит найти убедительную причину существования этого правила для локальных переменных; может быть, вы просто хотите убедиться, что он назначен действительно очень. Единственное, что я думаю, это позволяет вам использовать переменную в качестве временного хранилища при оценке инициализатора, например:
int a = method(a = somethingThatIsReallyExpensiveToCompute(), a);
будет эквивалентно:
int a;
{
int tmp = somethingThatIsReallyExpensiveToCompute();
a = method(tmp, tmp);
}
Лично я бы предпочел вторую форму кода, поскольку оценка первой кажется неясной.
@Holger интересный момент. Конечно, чисто пуповинный взгляд, но мне интересно, можно ли было бы включить ни один в область видимости и просто избежать обоих видов неясности ...!
Несмотря на приведенные выше выдержки из спецификации Java, с использованием только правила слева направо и правил приоритета, int a = a = 2; можно разбить на: int a = (a = 2);, затем int a; a = 2; a = a;.
Когда они исключили инициализатор переменной из своей области видимости,
int a = a;был допустимым оператором, то есть когда во внешней области есть другойa, как в вашем примере. Теперь, если это не непонятно ...