статические - типы данных java




Почему инициализация переменной для выражения присваивания[String x=(x=y)] компилируется? (2)

Как это компилируется без ошибок? Насколько я понимаю, компилятор проверяет тип переменной (в данном случае String ), а затем проверяет, соответствует ли тип выражения в правой части типу переменной (или хотя бы подтипу, но давайте придерживаться простого случая с класс String поскольку он окончательный).

public class InitClass {
  public static void main(String[] args) {
    String str = (str = "hello");
    System.out.println(str);
  }
}

Мой вопрос: как компилируется str = "hello" ? Компилятор уже знает, что str должен иметь тип String ?


Ваш случай эквивалентен

String str;
str = (str = "hello");

Хотя задания выглядят смешно, концептуально нет ничего плохого.

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

Локальная переменная имеет более строгое требование (чем полевая переменная) - она ​​должна быть назначена первой перед использованием ее значения. Например, это не скомпилируется, потому что локальная переменная читается перед назначением.

String str;  // local variable
str = str;   // error, try to read `str` before it's assigned

Переменная поля всегда имеет начальное значение по умолчанию; тем не менее, компилятор проверяет наличие явных ошибок программиста

int x = x+1;  // error. x is field variable.

Но это не катастрофично, если такая проверка не удалась, так как x имеет значение 0 до явного присвоения

int x;
{ x=x+1; } // ok. x==0, then x==1 after assignment

Однако, если x является final , приведенный выше код завершается ошибкой, потому что компилятор требует определенного присвоения x прежде чем читать x , то же самое требование для локальной переменной. Но эту проверку можно обойти, потому что невозможно полностью проанализировать и предотвратить ее для переменных поля

final int x = (this).x+1;  // compiles!

В некоторых случаях компилятор выходит за борт, предотвращая законные случаи использования, включающие лямбду

Runnable r1 = ()->System.out.println(r1);  // r1 is a field variable 

Нет ничего концептуально проблемного в этом случае использования; это может быть обойдено (this). тоже.


При оценке выражения присваивания

Во-первых, левый операнд вычисляется для создания переменной. Если эта оценка завершается преждевременно, то выражение присваивания завершается преждевременно по той же причине; правый операнд не оценивается и присваивания не происходит.

Это производит переменную str . затем

В противном случае вычисляется правый операнд . Если эта оценка завершается преждевременно, то выражение присваивания завершается преждевременно по той же причине, и назначение не происходит.

В вашем примере правый операнд сам по себе является другим выражением присваивания. Таким образом, str , правый операнд оператора присваивания, снова вычисляется для получения переменной str . затем

В противном случае значение правого операнда преобразуется в тип левой переменной, подвергается преобразованию набора значений (§5.1.13) в соответствующий набор стандартных значений (не набор значений с расширенным показателем), и результат преобразования сохраняется в переменной.

Так что "hello" хранится в str . И с тех пор

Во время выполнения результатом выражения присваивания является значение переменной после присвоения. Результат выражения присваивания сам по себе не является переменной.

Результатом присвоения "hello" str является значение "hello" , это значение снова сохраняется в str .





java