Ограничение типов в переменных цикла в Java, C и C ++ - PullRequest
5 голосов
/ 27 августа 2009

Почему Java, C и C ++ (возможно, и другие языки) не допускают более одного типа для переменных цикла for? Например:

for (int i = 0; i < 15; i++)

в этом случае у нас есть переменная цикла i, которая является счетчиком цикла.

Но мне может понадобиться другая переменная, область действия которой ограничена циклом, а не каждой итерацией. Например:

for (int i = 0, variable = obj.operation(); i < 15; i++) { ... }

Я храню obj.operation() возвращаемых данных в variable, потому что я хочу использовать их only внутри цикла. Я не хочу, чтобы variable хранилось в памяти и не оставалось видимым после выполнения цикла. Не только для освобождения места в памяти, но и для предотвращения нежелательного поведения, вызванного неправильным использованием variable.

Следовательно, переменные цикла полезны, но широко не поддерживаются из-за ограничения типа. Представьте, что метод operation() возвращает длинное значение. Если это произойдет, я не смогу пользоваться преимуществами переменных цикла без приведения и потери данных. Следующий код не компилируется в Java:

for (int i = 0, long variable = obj.operation(); i < 15; i++) { ... }

Опять же, кто-нибудь знает, почему существует такое ограничение типа?

Ответы [ 6 ]

21 голосов
/ 27 августа 2009

Это ограничение существует, потому что ваше требование довольно необычно и может быть получено с помощью очень похожей (и лишь немного более многословной) конструкции. Java поддерживает блоки анонимного кода для ограничения области видимости, если вы действительно хотите сделать это:

public void method(int a) {
  int outerVar = 4;
  {
    long variable = obj.operation();
    for (int i = 0; i < 15; i++) { ... }
  }
}
6 голосов
/ 27 августа 2009

Ваш пример:

for (int i = 0, long variable = obj.operation(); i < 15; i++) { ... }

является незаконным по той же причине, что:

int i = 0, long variable = obj.operation();

было бы незаконно само по себе. Запятая не начинает новое утверждение. Обе части, до и после запятой, являются частью одного утверждения. Этот оператор объявляет и инициализирует список int переменных. Хорошо, это то, что идентификатор int в начале строки говорит компилятору, так или иначе. Идентификатор long после запятой является ошибкой, так как для объявления переменной (переменных) другого типа вы должны начать новый оператор.

Поскольку вы не можете объявлять переменные двух разных типов в одном операторе, вы должны объявить одну из них вне инициализатора for.

2 голосов
/ 27 августа 2009

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

1 голос
/ 27 августа 2009

@ jsight прав, но я думаю, что настоящая причина - синтаксическая простота. Предположим, что Java допускает либо тип, либо имя новой переменной после первой запятой. Поскольку Java не требует предварительного объявления, идентификатор, следующий за запятой, может быть новым именем переменной, существующим именем класса с именем класса, с которым ранее не встречались. Теперь должно быть возможно иметь дело с этим, но:

  1. Это делает грамматику более сложной, возможно, способами, которые не сразу очевидны.
  2. Это делает фазу синтаксического анализа компилятора Java более сложной.
  3. Это усложняет работу других инструментов, обрабатывающих исходный код Java.
  4. Вероятно, это приводит к более расплывчатым и / или вводящим в заблуждение сообщениям об ошибках компилятора, если в цикле for есть синтаксическая ошибка.

(IMO, синтаксическая сложность - одна из ошибок C и особенно C ++. Я много занимался кодированием в обоих, но я все еще считаю, что сообщения о синтаксических ошибках трудно декодировать иногда.)

0 голосов
/ 27 августа 2009

В соответствии со спецификацией инициализация оператора for может быть списком выражений оператора, которые оцениваются и отбрасываются, или оператором объявления одной переменной. Оператор объявления переменной может объявлять несколько переменных, но все они одного типа.

Так что вы можете сделать это:

for (int i = 0, variable = obj.operation(); i < 15; i++) { ... }

Но в этом случае переменная будет определяться как int.

0 голосов
/ 27 августа 2009

Просто угадайте - объявить "длинную переменную" внутри цикла очень просто, а поскольку Java нацелена на простоту, дизайнеры могут не почувствовать необходимость добавлять поддержку того, что вы хотите.

...