2009-08-26 4 views
3

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

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

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

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

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

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

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

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

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

ответ

20

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

public void method(int a) { 
    int outerVar = 4; 
    { 
    long variable = obj.operation(); 
    for (int i = 0; i < 15; i++) { ... } 
    } 
} 
+0

Это то, что я хотел. работает и на C/C++. Спасибо! если бы я мог дать +1;) – fjsj

+0

Ответ работает, но использование анонимных блоков, подобных этому, является необычным стилем, я бы не использовал его в своих программах. – Jesper

+0

Я встречаюсь с этим ограничением очень часто, например, когда мне нужно преобразовать Итератор или другую последовательную структуру на основе индекса. Init для цикла for является хорошим местом для размещения переменных, которые необходимы только в контексте этого цикла. Например, это будет хороший цикл для заполнения случайного массива: для (int i = 0, final Random random = new Random(); i Fixpoint

0

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

+1

Это будет охватывать переменную за итерацию, а не за цикл – Jesse

+0

Как сказал Джесси, меня интересует область цикла. Я не хочу потерять значение переменной на каждой итерации. – fjsj

2

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

+1

Нет, это законно в Java: для (int i = 0, j = 5; i

+0

Эту, я беру это обратно. Я думаю, что неправильно прочитал ваш комментарий. –

0

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

Таким образом, вы можете сделать это:

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

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

+1

Мне это известно, но я хочу объявить более чем одну переменную с разными типами. – fjsj

1

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

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

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

3

Ваш пример:

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

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

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

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

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