ГЛАВА 16
Определенное Присвоение
Каждая локальная переменная (§14.4) и каждый пробел final
у поля (§4.5.4) (§8.3.1.2) должно быть определенно присвоенное значение, когда любой доступ его значения происходит. Компилятор Java должен выполнить определенный консервативный анализ потоков, чтобы удостовериться что для каждого доступа локальной переменной или пробела final
поле f, f определенно присваивается перед доступом; иначе ошибка времени компиляции должна произойти.
Точно так же каждый пробел final
переменная должна быть присвоена самое большее однажды; это должно быть определенно неприсвоенным, когда присвоение на это происходит. Компилятор Java должен выполнить определенный консервативный анализ потоков, чтобы удостовериться что для каждого присвоения на пробел final
переменная, переменная является определенно неприсвоенной перед присвоением; иначе ошибка времени компиляции должна произойти.
Остаток от этой главы посвящается точному объяснению слов, "определенно присвоенных прежде, чем" и "определенно отменил присвоение прежде".
Идея позади определенного присвоения состоит в том что присвоение на локальную переменную или пробел final
поле должно произойти на каждом возможном пути выполнения к доступу. Точно так же идея позади определенного неприсвоения состоит в том что никакое другое присвоение на пробел final
переменной разрешают произойти на любом возможном пути выполнения к присвоению. Анализ принимает во внимание структуру операторов и выражений; это также обеспечивает специальный режим операторов выражения !
, &&
, ||
, и ? :
, и оцененных булевской переменной константных выражений.
Например, компилятор Java распознает это k
определенно присваивается перед его доступом (как параметр вызова метода) в коде:
{
int k;
if (v > 0 && (k = System.in.read()) >= 0)
System.out.println(k);
}
потому что доступ происходит только если значение выражения:
v > 0 && (k = System.in.read()) >= 0
истина, и значение может быть true
только если присвоение на k
выполняется (более должным образом, оценивается).
Точно так же компилятор Java распознает что в коде:
{
int k;
while (true) {
k = n;
if (k >= 5) break;
n = 6;
}
System.out.println(k);
}
переменная k
определенно присваивается while
оператор, потому что выражение условия true
никогда не имеет значение false
, так только break
оператор может вызвать while
оператор, чтобы обычно завершаться, и k
определенно присваивается перед break
оператор.
С другой стороны, код
{
int k;
while (n < 4) {
k = n;
if (k >= 5) break;
n = 6;
}
System.out.println(k); // k is not "definitely assigned" before this
}
должен быть отклонен компилятором Java, потому что в этом случае while
оператор, как гарантируют, не выполнит свое тело, насколько правила определенного присвоения затрагиваются.
За исключением специального режима условных булевых операторов &&
, ||
, и ? :
и оцененных булевской переменной константных выражений, значения выражений не принимаются во внимание в анализе потоков.
Например, компилятор Java должен произвести ошибку времени компиляции для кода:
{
int k;
int n = 5;
if (n > 2)
k = 3;
System.out.println(k); // k is not "definitely assigned" before this
}
даже при том, что значение n
известен во время компиляции, и в принципе можно быть известно во время компиляции что присвоение на k
будет всегда выполняться (более должным образом, оцениваться). Компилятор Java должен работать согласно правилам, размеченным в этом разделе. Правила распознают только константные выражения; в этом примере, выражении n
>
2
не константное выражение как определено в §15.28.
Как другой пример, компилятор Java примет код:
void flow(boolean flag) {
int k;
if (flag)
k = 3;
else
k = 4;
System.out.println(k);
}
до определенного присвоения k
затрагивается, потому что правила, обрисованные в общих чертах в этом разделе, позволяют этому говорить это k
присваивается независимо от того, является ли флаг true
или false
. Но правила не принимают изменение:
void flow(boolean flag) {
int k;
if (flag)
k = 3;
if (!flag)
k = 4;
System.out.println(k); // k is not "definitely assigned" before here
}
и так компиляция этой программы должна заставить ошибку времени компиляции происходить.
Связанный пример иллюстрирует правила определенного неприсвоения. Компилятор Java примет код:
void unflow(boolean flag) {
final int k;
if (flag) {
k = 3;
System.out.println(k);
}
else {
k = 4;
System.out.println(k);
}
}
до определенного неприсвоения k
затрагивается, потому что правила, обрисованные в общих чертах в этом разделе, позволяют этому говорить это k
присваивается самое большее однажды (действительно, точно однажды) независимо от того, является ли флаг true
или false
. Но правила не принимают изменение:
void unflow(boolean flag) {
final int k;
if (flag) {
k = 3;
System.out.println(k);
}
if (!flag) {
k = 4; // k is not "definitely unassigned" before here
System.out.println(k);
}
}
и так компиляция этой программы должна заставить ошибку времени компиляции происходить.
Чтобы точно определить все случаи определенного присвоения, правила в этом разделе определяют несколько технических терминов:
- присваивается ли переменная определенно перед оператором или выражением;
- является ли переменная определенно неприсвоенной перед оператором или выражением;
- присваивается ли переменная определенно после оператора или выражения; и
- является ли переменная определенно неприсвоенной после оператора или выражения.
Для оцененных булевской переменной выражений последние два усовершенствованы в четыре случая:
- присваивается ли переменная определенно после выражения когда истина;
- является ли переменная определенно неприсвоенной после выражения когда истина;
- присваивается ли переменная определенно после выражения когда ложь; и
- является ли переменная определенно неприсвоенной после выражения когда ложь.
Здесь, когда истина и когда ложь обращаются к значению выражения.
Например, локальная переменная k определенно присваивается значение после оценки выражения
a && ((k=m) > 5)
когда выражение true
но не, когда выражение false
(потому что, если a
false
, тогда присвоение на k
не обязательно выполняется (более должным образом, оценивается)).
Фраза "V определенно присваивается, после X" (то, где V локальная переменная и X, является оператором или выражением) означает "V, определенно присваивается после X, если X обычно завершается". Если X завершается резко, присвоение не должно произойти, и правила, утвержденные здесь, принимают это во внимание. Специфическое последствие этого определения - то, что "V определенно присваивается после break;
"всегда истина! Поскольку a break
оператор никогда обычно не завершается, это вырождено истинно, что V был присвоен значение если break
оператор обычно завершается.
Точно так же оператор "V является определенно неприсвоенным, после X" (то, где V переменная и X, является оператором или выражением) означает "V, является определенно неприсвоенным после X, если X обычно завершается". Еще более специфическое последствие этого определения - то, что "V является определенно неприсвоенным после break;
"всегда истина! Поскольку a break
оператор никогда обычно не завершается, это вырождено истинно, что V не был присвоен значение если break
оператор обычно завершается. (В этом отношении это также вырождено истинно, что луна делается из зеленого сыра если break
оператор обычно завершается.)
В целом, есть четыре возможности для переменной V после оператора, или выражение было выполнено:
- V определенно присваивается и не определенно неприсвоенный. (Правила анализа потоков доказывают, что присвоение на V произошло.)
- V является определенно неприсвоенным и определенно не присваивается. (Правила анализа потоков доказывают, что присвоение на V не произошло.)
- V определенно не присваивается и не определенно неприсвоенный. (Правила не могут доказать, произошло ли присвоение на V.)
- V определенно присваивается и определенно неприсвоенный. (Для оператора или выражения невозможно завершиться обычно.)
Чтобы сократить правила, общепринятое сокращение "эквивалентность" используется, чтобы означать "если и только если". Мы также используем соглашение сокращения: если правило содержит одно или более возникновений" [un] присвоенный", тогда оно обозначает два правила, один с каждым возникновением" [un] присвоенный" замененный "определенно присвоенным" и один с каждым возникновением" [un] присвоенный" замененный "определенно неприсвоенным".
Например:
V [un], присвоенный после пустой эквивалентности оператора, которая это [un], присвоенный перед пустым оператором.
как должны понимать, обозначает два правила:
- V определенно присваивается после пустой эквивалентности оператора это определенно присваивается перед пустым оператором.
- V является определенно неприсвоенным после пустой эквивалентности оператора это является определенно неприсвоенным перед пустым оператором.
Определенный анализ неприсвоения операторов цикла повышает специальную проблему. Рассмотрите оператор while
(
e)
S. Чтобы определить, является ли V определенно неприсвоенным в пределах некоторого подвыражения e, мы должны определить, является ли V определенно неприсвоенным прежде e. Можно было бы спорить по аналогии с правилом для определенного присвоения (§16.2.9), который V является определенно неприсвоенным, прежде e эквивалентность это является определенно неприсвоенным перед while
оператор. Однако, такое правило является несоответствующим в наших целях. Если e оценит к истине, то оператор S будет выполняться. Позже, если V присваивается S, то в следующей итерации (ях) V будет уже присвоен, когда e оценивается. По правилу, предложенному выше, было бы возможно присвоиться V многократно, который является точно, чего мы стремились избежать, представляя эти правила.
Пересмотренное правило было бы: "V является определенно неприсвоенным, прежде e эквивалентность это является определенно неприсвоенным перед, в то время как оператор и определенно отменил присвоение после S". Однако, когда мы формулируем правило для S, мы находим: "V является определенно неприсвоенным, прежде S эквивалентность это является определенно неприсвоенным после e когда истина". Это приводит к зацикливанию. В действительности, V является определенно неприсвоенным перед условием цикла e, только если оно является неприсвоенным после цикла в целом!
Мы повреждаем этот порочный круг, используя гипотетический анализ условия цикла и тела. Например, если мы предполагаем, что V является определенно неприсвоенным, прежде e (независимо от того, является ли V действительно определенно неприсвоенным прежде e), и может тогда доказать, что V был определенно неприсвоенным, после e тогда мы знаем, что e не присваивается V. Это утверждается более формально как:
Принятие V является определенно неприсвоенным, прежде e, V является определенно неприсвоенным после e.
Изменения на вышеупомянутом анализе используются, чтобы определить хорошо основанные определенные правила неприсвоения для всех операторов цикла на языке.
Всюду по остальной части этой главы мы, если явно не утверждено иначе, запишем V, чтобы представить локальную переменную или пробел final
поле (для правил определенного присвоения) или пробел final
переменная (для правил определенного неприсвоения). Аналогично, мы будем использовать a, b, c, и e, чтобы представить выражения, и S и T, чтобы представить операторы.
16.1 Определенное Присвоение и Выражения
16.1.1 Булевы Константные выражения
- V [un], присвоенный после любого константного выражения, значение которого
true
когда ложь.
- V [un], присвоенный после любого константного выражения, значение которого
false
когда истина.
Поскольку константное выражение, значение которого true
никогда не имеет значение false
, и константное выражение, значение которого false
никогда не имеет значение true
, два предыдущих правила вырождено удовлетворяются. Они полезны в анализе выражений, включающих операторы &&
(§16.1.2), ||
(§16.1.3), !
(§16.1.4), и ?
:
(§16.1.5).
- V [un], присвоенный после любого константного выражения, значение которого
true
когда истинная эквивалентность V [un], присвоенный перед константным выражением.
- V [un], присвоенный после любого константного выражения, значение которого
false
когда ложная эквивалентность V [un], присвоенный перед константным выражением.
- V [un], присвоенный после того, как оцененное булевской переменной константное выражение e эквивалентность V [un], присвоенный после e, когда истина и V [un], присвоенный после e когда ложь. (Это эквивалентно высказыванию, которое V [un], присвоенный после того, как e эквивалентность V [un], присвоенный прежде e.)
16.1.2 Булев оператор &&
- V [un], присвоенный после a
&&
b, когда истинная эквивалентность V [un], присвоенный после b когда истина.
- V [un], присвоенный после a
&&
b, когда ложная эквивалентность V [un], присвоенный после, когда ложь и V [un], присвоенный после b когда ложь.
- V [un], присвоенный прежде, чем эквивалентность V будет [un], присвоенный прежде a
&&
b.
- V [un], присвоенный прежде, чем b эквивалентность V будет [un], присвоенный после когда истина.
- V [un], присвоенный после a
&&
b эквивалентность V [un], присвоенный после a &&
b, когда истина и V [un], присвоенный после a &&
b, когда ложь.
16.1.3 Булев оператор ||
- V [un], присвоенный после a
||
b, когда истинная эквивалентность V [un], присвоенный после, когда истина и V [un], присвоенный после b когда истина.
- V [un], присвоенный после a
||
b, когда ложная эквивалентность V [un], присвоенный после b когда ложь.
- V [un], присвоенный прежде, чем эквивалентность V будет [un], присвоенный прежде a
||
b.
- V [un], присвоенный прежде, чем b эквивалентность V будет [un], присвоенный после когда ложь.
- V [un], присвоенный после a
||
b эквивалентность V [un], присвоенный после a ||
b, когда истина и V [un], присвоенный после a ||
b, когда ложь.
16.1.4 Булев оператор!
- V [un], присвоенный после
!
когда истинная эквивалентность V [un], присвоенный после когда ложь.
- V [un], присвоенный после
!
когда ложная эквивалентность V [un], присвоенный после когда истина.
- V [un], присвоенный прежде, чем эквивалентность V будет [un], присвоенный прежде
!
a.
- V [un], присвоенный после
!
эквивалентность V [un], присвоенный после !
когда истина и V [un], присвоенный после !
когда ложь. (Это эквивалентно высказыванию, которое V [un], присвоенный после !
эквивалентность V [un], присвоенный после a.)
16.1.5 Булев оператор?:
Предположите, что b и c являются оцененными булевской переменной выражениями.
- V [un], присвоенный после a
?
b :
c, когда истинная эквивалентность V [un], присвоенный после b, когда истина и V [un], присвоенный после c когда истина.
- V [un], присвоенный после a
?
b :
c, когда ложная эквивалентность V [un], присвоенный после b, когда ложь и V [un], присвоенный после c когда ложь.
- V [un], присвоенный прежде, чем эквивалентность V будет [un], присвоенный прежде a
?
b :
c.
- V [un], присвоенный прежде, чем b эквивалентность V будет [un], присвоенный после когда истина.
- V [un], присвоенный прежде, чем c эквивалентность V будет [un], присвоенный после когда ложь.
- V [un], присвоенный после a
?
b :
c эквивалентность V [un], присвоенный после a ?
b :
c, когда истина и V [un], присвоенный после a ?
b :
c, когда ложь.
16.1.6 Условный Оператор?:
Предположите, что b и c являются выражениями, которые не оцениваются булевской переменной.
- V [un], присвоенный после a
?
b :
c эквивалентность V [un], присвоенный после того, как b и V [un], присвоенный после c.
- V [un], присвоенный прежде, чем эквивалентность V будет [un], присвоенный прежде a
?
b :
c.
- V [un], присвоенный прежде, чем b эквивалентность V будет [un], присвоенный после когда истина.
- V [un], присвоенный прежде, чем c эквивалентность V будет [un], присвоенный после когда ложь.
16.1.7 Выражения присвоения
Рассмотрите выражение a присвоения =
b, a +=
b, a -=
b, a *=
b, a /=
b, a %=
b, a <<=
b, a >>=
b, a >>>=
b, a &=
b, a |=
b, или a ^=
b.
- V определенно присваивается после эквивалентности выражения присвоения или V или V определенно присваивается после b.
- V является определенно неприсвоенным после эквивалентности выражения присвоения не V и V является определенно неприсвоенным после b.
- V [un], присвоенный прежде, чем эквивалентность V будет [un], присвоенный перед выражением присвоения.
- V [un], присвоенный прежде, чем b эквивалентность V будет [un], присвоенный после a. Отметьте это, если V и V определенно не присваивается перед составным присвоением, таким как a
&=
b, затем ошибка времени компиляции обязательно произойдет. Первое правило для определенного вышеизложенного присвоения включает разобщенное "V" даже для составных выражений присвоения, не только простых присвоений, так, чтобы V, как полагали, был определенно присвоен в более поздних точках в коде. Включая разобщенное "V" не влияет на выбор из двух альтернатив относительно того, является ли программа приемлемой или приведет к ошибке времени компиляции, но это влияет, сколько различных точек в коде может быть расценено как ошибочные, и так практически это может улучшить качество сообщения об ошибке. Подобный комментарий применяется к включению соединенного "не V" в первом правиле для определенного вышеизложенного неприсвоения.
Если выражение присвоения оценивается булевской переменной, то эти правила также применяются:
- V [un], присвоенный после выражения присвоения, когда истинная эквивалентность V [un], присвоенный после выражения присвоения.
- V [un], присвоенный после выражения присвоения, когда ложная эквивалентность V [un], присвоенный после выражения присвоения.
16.1.8 Операторы ++ и--
- V определенно присваивается после
++
a, --
a, a++
, или a--
эквивалентность или V или V определенно присваивается после выражения операнда.
- V является определенно неприсвоенным после
++
a, --
a, a++
, или a--
эквивалентность не V и V является определенно неприсвоенной после выражения операнда.
- V [un], присвоенный прежде, чем эквивалентность V будет [un], присвоенный прежде
++
a, --
a, a++
, или a--
.
16.1.9 Другие Выражения
Если выражение не является булевым константным выражением, и не является предынкрементным выражением ++
a, преддекрементное выражение --
a, постинкрементное выражение a++
, постдекрементное выражение a--
, логическое дополнительное выражение !
a, условное выражение - и выражение a &&
b, условное выражение - или выражение a ||
b, условное выражение a ?
b :
c, или выражение присвоения, тогда следующие правила применяются:
- Если у выражения нет никаких подвыражений, V [un], присвоенный после того, как эквивалентность выражения V [un], присвоенный перед выражением. Этот случай применяется к литералам, именам,
this
(и квалифицированный и неполный), неполные выражения создания экземпляра класса без параметров, инициализированные выражения создания массива, инициализаторы которых не содержат выражений, неполных выражений доступа к полю суперкласса, названных вызовами метода без параметров, и неполными вызовами метода суперкласса без параметров.
- Если у выражения есть подвыражения, V [un], присвоенный после того, как эквивалентность выражения V [un], присвоенный после его самого правого непосредственного подвыражения.
Есть часть тонкого рассуждения позади утверждения, что переменная V, как может быть известно, является определенно неприсвоенной после вызова метода. Взятый отдельно, по номиналу и без квалификации, такое утверждение является не всегда истиной, потому что вызванный метод может выполнить присвоения. Но нужно помнить, что в целях языка программирования Java понятие определенного неприсвоения применяется только, чтобы очистить final
переменные. Если V пробел final
локальная переменная, тогда только метод, которому принадлежит его объявление, может выполнить присвоения на V. Если V пробел final
поле, тогда только конструктор или инициализатор для класса, содержащего объявление для V, может выполнить присвоения на V; никакой метод не может выполнить присвоения на V. Наконец, явные вызовы конструктора (§8.8.5) обрабатываются особенно (§16.8); хотя они синтаксически подобны операторам выражения, содержащим вызовы метода, они не операторы выражения, и поэтому правила этого раздела не применяются к явным вызовам конструктора.
Для любого непосредственного подвыражения y выражения x, V [un], присвоенный прежде y эквивалентность, одна из следующих ситуаций является истиной:
- y является крайним левым непосредственным подвыражением x, и V [un], присвоенный прежде x.
- y является правым операндом бинарного оператора, и V [un], присвоенный после левого операнда.
- x является доступом массива, y является подвыражением в пределах скобок, и V [un], присвоенный после подвыражения перед скобками.
- x является основным выражением вызова метода, y является первым выражением параметра в выражении вызова метода, и V [un], присвоенный после основного выражения, которое вычисляет целевой объект.
- x является выражением вызова метода или выражением создания экземпляра класса; y является выражением параметра, но не первым; и V [un], присвоенный после выражения параметра налево от y.
- x является квалифицированным выражением создания экземпляра класса, y является первым выражением параметра в выражении создания экземпляра класса, и V [un], присвоенный после основного выражения, которое вычисляет объект квалификации.
- x является выражением создания экземпляра массива; y является выражением размерности, но не первым; и V [un], присвоенный после выражения размерности налево от y.
- x является выражением создания экземпляра массива, инициализированным через инициализатор массива; y является инициализатором массива в x; и V [un], присвоенный после выражения размерности налево от y.
16.2 Определенное Присвоение и Операторы
16.2.1 Пустые Операторы
- V [un], присвоенный после пустой эквивалентности оператора, которая это [un], присвоенный перед пустым оператором.
16.2.2 Блоки
- Пустое заключительное задействованное поле V определенно присваивается (и кроме того не является определенно неприсвоенным) перед блоком, который является телом любого метода в пределах V.
- Локальная переменная V является определенно неприсвоенной (и кроме того определенно не присваивается) перед блоком, который является телом конструктора, метода, инициализатора экземпляра или статического инициализатора, который объявляет V.
- Позвольте C быть классом, объявленным в рамках V. Затем:
- V определенно присваивается перед блоком, который является телом любого конструктора, метод, инициализатор экземпляра или статический инициализатор, объявленный в эквивалентности C V, определенно присваиваются перед объявлением К. Ноута, что нет никаких правил, которые позволили бы нам приходить к заключению, что V является определенно неприсвоенным перед блоком, который является телом любого конструктора, метода, инициализатора экземпляра или статического инициализатора, объявленного в C. Мы можем неофициально прийти к заключению, что V не является определенно неприсвоенным перед блоком, который является телом любого конструктора, метод, инициализатор экземпляра или статический инициализатор, объявленный в C, но нет никакой потребности в таком правиле, которое будет утверждено явно.
- V [un], присвоенный после пустой блочной эквивалентности, которая это [un], присвоенный перед пустым блоком.
- V [un], присвоенный после непустой блочной эквивалентности, которая это [un], присвоенный после последнего оператора в блоке.
- V [un], присвоенный перед первым оператором блочной эквивалентности, которая это [un], присвоенный перед блоком.
- V [un], присвоенный перед любым другим оператором S блочной эквивалентности, которая это [un], присвоенный после оператора, сразу предшествующего S в блоке.
16.2.3 Операторы объявления Локального класса
- V [un], присвоенный после эквивалентности оператора объявления локального класса, которая это [un], присвоенный перед оператором объявления локального класса.
16.2.4 Операторы объявления Локальной переменной
- V [un], присвоенный после оператора объявления локальной переменной, который не содержит переменной эквивалентности инициализаторов, которая это [un], присвоенный перед оператором объявления локальной переменной.
- V определенно присваивается после оператора объявления локальной переменной, который содержит по крайней мере одну переменную эквивалентность инициализатора или она определенно присваивается после того, как последний переменный инициализатор в операторе объявления локальной переменной или последний переменный инициализатор в объявлении находятся в операторе объявления, который объявляет V.
- V является определенно неприсвоенным после оператора объявления локальной переменной, который содержит по крайней мере одну переменную эквивалентность инициализатора, она является определенно неприсвоенной после того, как последний переменный инициализатор в операторе объявления локальной переменной и последний переменный инициализатор в объявлении не находятся в операторе объявления, который объявляет V.
- V [un], присвоенный перед первой переменной эквивалентностью инициализатора, которая это [un], присвоенный перед оператором объявления локальной переменной.
- V определенно присваивается прежде, чем любой переменный инициализатор e кроме первого в эквивалентности оператора объявления локальной переменной или V определенно присваивается после того, как переменный инициализатор налево от e или выражение инициализатора налево от e находятся в операторе объявления, который объявляет V.
- V является определенно неприсвоенным прежде, чем любой переменный инициализатор e кроме первого в эквивалентности оператора объявления локальной переменной V является определенно неприсвоенным после того, как переменный инициализатор налево от e и выражение инициализатора налево от e не находятся в операторе объявления, который объявляет V.
16.2.5 Помеченные операторы
- V [un], присвоенный после помеченного оператора L
:
S (где L является меткой) эквивалентность V [un], присвоенный после того, как S и V [un], присвоенный перед каждым break
оператор, который может выйти из помеченного оператора L:
S.
- V [un], присвоенный прежде, чем S эквивалентность V будет [un], присвоенный прежде L
:
S.
16.2.6 Операторы выражения
- V [un], присвоенный после оператора e выражения
;
эквивалентность это [un], присвоенный после e.
- V [un], присвоенный прежде e эквивалентность, которая это [un], присвоенный прежде e
;
.
16.2.7 if
Операторы
Следующие правила применяются к оператору if
(
e)
S:
- V [un], присвоенный после
if
(
e)
S эквивалентность V [un], присвоенный после того, как S и V [un], присвоенный после e когда ложь.
- V [un], присвоенный прежде, чем e эквивалентность V будет [un], присвоенный прежде
if
(
e)
S.
- V [un], присвоенный прежде, чем S эквивалентность V будет [un], присвоенный после e когда истина.
Следующие правила применяются к оператору if
(
e)
S else
T:
- V [un], присвоенный после
if
(
e)
S else
T эквивалентность V [un], присвоенный после того, как S и V [un], присвоенный после T.
- V [un], присвоенный прежде, чем e эквивалентность V будет [un], присвоенный прежде
if
(
e)
S else
T.
- V [un], присвоенный прежде, чем S эквивалентность V будет [un], присвоенный после e когда истина.
- V [un], присвоенный прежде, чем T эквивалентность V будет [un], присвоенный после e когда ложь.
16.2.8 switch
Операторы
- V [un], присвоенный после a
switch
эквивалентность оператора все следующее является истиной:
- Любой там - a
default
метка в switch
блок или V [un], присвоенный после выражения переключателя.
- Любой там не метки переключателя в
switch
блок, которые не начинают группу оператора блока (то есть, нет никаких меток переключателя сразу перед"}
"это заканчивает блок переключателя), или V [un], присвоенный после выражения переключателя.
- Любой
switch
блок не содержит групп оператора блока, или V [un], присвоенный после последнего оператора блока последней группы оператора блока.
- V [un], присвоенный перед каждым
break
оператор, который может выйти switch
оператор.
- V [un], присвоенный прежде, чем эквивалентность выражения переключателя V будет [un], присвоенный перед
switch
оператор.
Если блок переключателя содержит по крайней мере одну группу оператора блока, то следующие правила также применяются:
- V [un], присвоенный прежде, чем первый оператор блока первой группы оператора блока в блочной эквивалентности переключателя V будет [un], присвоенный после выражения переключателя.
- V [un], присвоенный прежде, чем первый оператор блока любой группы оператора блока кроме первой эквивалентности V будет [un], присвоенный после того, как выражение переключателя и V [un], присвоенный после последнего оператора блока предыдущей группы оператора блока.
- V [un], присвоенный прежде, чем любой оператор блока кроме первой из любой группы оператора блока в блочной эквивалентности переключателя V будет [un], присвоенный после последнего оператора блока предыдущей группы оператора блока.
16.2.9 while
Операторы
- V [un], присвоенный после
while
(
e)
S эквивалентность V [un], присвоенный после e, когда ложь и V [un], присвоенный перед каждым break
оператор тот, для который while
оператор является целью повреждения.
- V определенно присваивается, прежде e эквивалентность V определенно присваивается перед
while
оператор.
- V является определенно неприсвоенным, прежде e эквивалентность все следующие условия содержат:
- V является определенно неприсвоенным перед
while
оператор.
- Принятие V является определенно неприсвоенным, прежде e, V является определенно неприсвоенным после S.
- Принятие V является определенно неприсвоенным, прежде e, V является определенно неприсвоенным перед каждым
continue
оператор тот, для который while
оператор является продолжать целью.
- V [un], присвоенный прежде, чем S эквивалентность V будет [un], присвоенный после e когда истина.
16.2.10 do
Операторы
- V [un], присвоенный после
do
S while
(
e);
эквивалентность V [un], присвоенный после e, когда ложь и V [un], присвоенный перед каждым break
оператор тот, для который do
оператор является целью повреждения.
- V определенно присваивается, прежде S эквивалентность V определенно присваивается перед
do
оператор.
- V является определенно неприсвоенным, прежде S эквивалентность все следующие условия содержат:
- V является определенно неприсвоенным перед
do
оператор.
- Принятие V является определенно неприсвоенным, прежде S, V является определенно неприсвоенным после e когда истина.
- V [un], присвоенный прежде, чем e эквивалентность V будет [un], присвоенный после того, как S и V [un], присвоенный перед каждым
continue
оператор тот, для который do
оператор является продолжать целью.
16.2.11 for
Операторы
- V [un], присвоенный после a
for
эквивалентность оператора оба из следующего является истиной:
- Или выражение условия не присутствует или V, [un], присвоенный после выражения условия когда ложь.
- V [un], присвоенный перед каждым
break
оператор тот, для который for
оператор является целью повреждения.
- V [un], присвоенный перед частью инициализации
for
эквивалентность оператора V [un], присвоенный перед for
оператор.
- V определенно присваивается перед частью условия
for
эквивалентность оператора V определенно присваивается после части инициализации for
оператор.
- V является определенно неприсвоенным перед частью условия
for
эквивалентность оператора все следующие условия содержит:
- V является определенно неприсвоенным после части инициализации
for
оператор.
- Принятие V является определенно неприсвоенным перед частью условия
for
оператор, V является определенно неприсвоенным после содержавшего оператора.
- Принятие V является определенно неприсвоенным перед содержавшим оператором, V является определенно неприсвоенным перед каждым
continue
оператор тот, для который for
оператор является продолжать целью.
- V [un], присвоенный перед содержавшей эквивалентностью оператора, любое из следующего является истиной:
- Выражение условия присутствует, и V [un], присвоенный после выражения условия когда истина.
- Никакое выражение условия не присутствует, и V [un], присвоенный после части инициализации
for
оператор.
- V [un], присвоенный перед частью приращения
for
эквивалентность оператора V [un], присвоенный после того, как содержавший оператор и V [un], присвоенный перед каждым continue
оператор тот, для который for
оператор является продолжать целью.
16.2.11.1 Часть инициализации
- Если часть инициализации
for
оператор является оператором объявления локальной переменной, правила §16.2.4 применяются.
- Иначе, если часть инициализации пуста, то V [un], присвоенный после того, как эквивалентность части инициализации V [un], присвоенный перед частью инициализации.
- Иначе, три правила применяются:
- V [un], присвоенный после того, как эквивалентность части инициализации V [un], присвоенный после последнего оператора выражения в части инициализации.
- V [un], присвоенный прежде, чем первый оператор выражения в эквивалентности части инициализации V будет [un], присвоенный перед частью инициализации.
- V [un], присвоенный прежде, чем оператор E выражения кроме первого в эквивалентности части инициализации V будет [un], присвоенный после оператора выражения, сразу предшествующего E.
16.2.11.2 Часть приращения
- Если часть приращения
for
оператор пуст, тогда V [un], присвоенный после того, как эквивалентность части приращения V [un], присвоенный перед частью приращения.
- Иначе, три правила применяются:
- V [un], присвоенный после того, как эквивалентность части приращения V [un], присвоенный после последнего оператора выражения в части приращения.
- V [un], присвоенный прежде, чем первый оператор выражения в эквивалентности части приращения V будет [un], присвоенный перед частью приращения.
- V [un], присвоенный прежде, чем оператор E выражения кроме первого в эквивалентности части приращения V будет [un], присвоенный после оператора выражения, сразу предшествующего E.
16.2.12 break, continue, return,
и throw
Операторы
- Условно, мы говорим, что V [un], присвоенный после любого
break
, continue
, return
, или throw
оператор. Понятие, что переменная" [un] присвоена после" оператора или выражения действительно, означает, "[un], присвоенный после оператора, или выражение обычно завершается". Поскольку a break
, continue
, return
, или throw
оператор никогда обычно не завершается, он вырождено удовлетворяет это понятие.
- В a
return
оператор с выражением e или a throw
оператор с выражением e, V [un], присвоенный прежде, чем e эквивалентность V будет [un], присвоенный перед return
или throw
оператор.
16.2.13 synchronized
Операторы
- V [un], присвоенный после
synchronized
(
e)
S эквивалентность V [un], присвоенный после S.
- V [un], присвоенный прежде, чем e эквивалентность V будет [un], присвоенный перед оператором
synchronized
(
e)
S.
- V [un], присвоенный прежде, чем S эквивалентность V будет [un], присвоенный после e.
16.2.14 try
Операторы
Эти правила применяются к каждому try
оператор, есть ли у этого a finally
блок:
- V [un], присвоенный перед
try
блочная эквивалентность V [un], присвоенный перед try
оператор.
- V определенно присваивается прежде a
catch
блочная эквивалентность V определенно присваивается перед try
блок.
- V является определенно неприсвоенным прежде a
catch
блочная эквивалентность V является определенно неприсвоенной после try
блок и V является определенно неприсвоенным перед каждым return
оператор, который принадлежит try
блок, каждый throw
оператор, который принадлежит try
блок, каждый break
оператор, который принадлежит try
блок и чья цель повреждения содержит (или), try
оператор, и каждый continue
оператор, который принадлежит try
блок и чей продолжают цель, содержит try
оператор.
Если a try
у оператора нет a finally
блок, тогда это правило также применяется:
- V [un], присвоенный после
try
эквивалентность оператора V [un], присвоенный после try
блок и V [un], присвоенный после каждого catch
блок в операторе попытки.
Если a try
у оператора действительно есть a finally
блок, тогда эти правила также применяются:
- V определенно присваивается после
try
эквивалентность оператора по крайней мере одно из следующего является истиной:
- V определенно присваивается после того, как блок попытки и V определенно присваивается после каждого
catch
блок в операторе попытки.
- V определенно присваивается после
finally
блок.
- V является определенно неприсвоенным после a
try
эквивалентность оператора V является определенно неприсвоенной после finally
блок.
- V определенно присваивается перед
finally
блочная эквивалентность V определенно присваивается перед try
оператор.
- V является определенно неприсвоенным перед
finally
блочная эквивалентность V является определенно неприсвоенной после try
блок и V является определенно неприсвоенным перед каждым return
оператор, который принадлежит try
блок, каждый throw
оператор, который принадлежит try
блок, каждый break
оператор, который принадлежит try
блок и чья цель повреждения содержит (или), try
оператор, и каждый continue
оператор, который принадлежит try
блок и чей продолжают цель, содержит try
оператор и V является определенно неприсвоенным после каждого catch
блок try
оператор.
16.3 Определенное Присвоение и Параметры
- Формальный параметр V из метода или конструктора определенно присваиваются (и кроме того не определенно неприсвоенный) перед телом метода или конструктора.
- Параметр исключения V из a
catch
пункт определенно присваивается (и кроме того не является определенно неприсвоенным) перед телом catch
пункт.
16.4 Определенные Инициализаторы Присвоения и Массива
- V [un], присвоенный после пустой эквивалентности инициализатора массива, которая это [un], присвоенный перед пустым инициализатором массива.
- V [un], присвоенный после непустой эквивалентности инициализатора массива, которая это [un], присвоенный после последнего переменного инициализатора в инициализаторе массива.
- V [un], присвоенный перед первым переменным инициализатором эквивалентности инициализатора массива, которая это [un], присвоенный перед инициализатором массива.
- V [un], присвоенный перед любым другим переменным инициализатором I из эквивалентности инициализатора массива, которая это [un], присвоенный после переменного инициализатора налево от меня в инициализаторе массива.
16.5 Определенное Присвоение и Анонимные классы
- V определенно присваивается прежде, чем объявление анонимного класса (§15.9.5), который объявляется в рамках V эквивалентностей V, определенно присваивается после выражения создания экземпляра класса, которое объявляет анонимный класс.
16.6 Определенное Присвоение и Типы элемента
Позвольте C быть классом, объявленным в рамках V. Затем:
- V определенно присваивается перед типом элемента (§8.5, §9.5) объявление эквивалентности C V определенно присваивается перед объявлением C.
16.7 Определенное Присвоение и Статические Инициализаторы
Позвольте C быть классом, объявленным в рамках V. Затем:
- V определенно присваивается прежде, чем инициализатор статической переменной эквивалентности C V определенно присваивается перед объявлением К. Ноута, что нет никаких правил, которые позволили бы нам приходить к заключению, что V является определенно неприсвоенным перед инициализатором статической переменной. Мы можем неофициально прийти к заключению, что V не является определенно неприсвоенным ни перед каким инициализатором статической переменной C, но нет никакой потребности в таком правиле, которое будет утверждено явно.
Позвольте C быть классом, и позволять V быть пробелом final
static
задействованное поле C, объявленного в C. Затем:
- V является определенно неприсвоенным (и кроме того определенно не присваивается) перед крайним левым
static
инициализатор или static
переменный инициализатор C.
- V [un], присвоенный прежде a
static
инициализатор или static
переменный инициализатор C кроме крайней левой эквивалентности V [un], присвоенный после предыдущего static
инициализатор или static
переменный инициализатор C.
Позвольте C быть классом, и позволять V быть пробелом final
static
задействованное поле C, объявленного в суперклассе C. Затем:
- V определенно присваивается (и кроме того не является определенно неприсвоенным) перед блоком, который является телом статического инициализатора C.
- V определенно присваивается (и кроме того не является определенно неприсвоенным) перед каждым инициализатором статической переменной C.
16.8 Определенное Присвоение, Конструкторы, и Инициализаторы Экземпляра
Позвольте C быть классом, объявленным в рамках V. Затем:
- V определенно присваивается прежде, чем инициализатор переменной экземпляра эквивалентности C V определенно присваивается перед объявлением К. Ноута, что нет никаких правил, которые позволили бы нам приходить к заключению, что V является определенно неприсвоенным перед инициализатором переменной экземпляра. Мы можем неофициально прийти к заключению, что V не является определенно неприсвоенным ни перед каким инициализатором переменной экземпляра C, но нет никакой потребности в таком правиле, которое будет утверждено явно.
Позвольте C быть классом, и позволять V быть пробелом final
не -static
задействованное поле C, объявленного в C. Затем:
- V является определенно неприсвоенным (и кроме того определенно не присваивается) перед крайним левым инициализатором экземпляра или инициализатором переменной экземпляра C.
- V [un], присвоенный перед инициализатором экземпляра, или инициализатор переменной экземпляра C кроме крайней левой эквивалентности V [un], присвоенный после предыдущего инициализатора экземпляра или инициализатора переменной экземпляра C.
Следующие правила содержат в пределах конструкторов класса C:
- V определенно присваивается (и кроме того не является определенно неприсвоенным) после альтернативного вызова конструктора.
- V является определенно неприсвоенным (и кроме того определенно не присваивается) перед явным или неявным вызовом конструктора суперкласса.
- Если у C нет никаких инициализаторов экземпляра или инициализаторов переменной экземпляра, то V определенно не присваивается (и кроме того является определенно неприсвоенным) после явного или неявного вызова конструктора суперкласса.
- Если у C есть по крайней мере один инициализатор экземпляра, или инициализатор переменной экземпляра тогда V [un], присвоенный после того, как явная или неявная эквивалентность вызова конструктора суперкласса V [un], присвоенный после самого правого инициализатора экземпляра или инициализатора переменной экземпляра C.
Позвольте C быть классом, и позволять V быть пробелом final
задействованное поле C, объявленного в суперклассе C. Затем:
- V определенно присваивается (и кроме того не является определенно неприсвоенным) перед блоком, который является телом конструктора, или инициализатором экземпляра C.
- V определенно присваивается (и кроме того не является определенно неприсвоенным) перед каждым инициализатором переменной экземпляра C.
Авторское право © Sun Microsystems, Inc 2000 года. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к jls@java.sun.com