О какой переменной здесь идет речь?

class Test {
  int a;

  void method() {
    a = 1;
    int a = a = 2;
    a = 3;
  }
}

В a много method. Что они все имеют в виду?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
0
116
1

Ответы 1

Это простой пример причудливости правил области видимости 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);
}

Лично я бы предпочел вторую форму кода, поскольку оценка первой кажется неясной.

Когда они исключили инициализатор переменной из своей области видимости, int a = a; был допустимым оператором, то есть когда во внешней области есть другой a, как в вашем примере. Теперь, если это не непонятно ...

Holger 21.09.2018 10:49

@Holger интересный момент. Конечно, чисто пуповинный взгляд, но мне интересно, можно ли было бы включить ни один в область видимости и просто избежать обоих видов неясности ...!

Andy Turner 21.09.2018 12:51

Несмотря на приведенные выше выдержки из спецификации Java, с использованием только правила слева направо и правил приоритета, int a = a = 2; можно разбить на: int a = (a = 2);, затем int a; a = 2; a = a;.

Mark Jeronimus 01.05.2019 10:49

Другие вопросы по теме