For infinito sem incremento

Tanto o Java, quanto o C, implementam uma otimização de compilador chamada dead code elimination. Ou seja, comandos vazios (fors, ifs, whiles, etc) são eliminados.

O teste ali não funciona pois essa otimização funciona se, E SOMENTE SE, não houver código dentro do for (alguns códigos, como uma declaração de variável sem que não se faça nada com ela, também são solenemente ignorados).

Se o for tiver qualquer efeito prático, ele vai ficar no código (e nem poderia ser diferente).

Em termos de otimização de compilador, tanto o Java quanto o C são bastante agressivos. Principalmente se, no caso do C, a opção O3 estiver ligada.

Outra situação bizarra do for é usa-lo com duas variáveis.

for(int i=0,int j=10; i < 5 && j > 0; i++ , j--) { }

Compreendo apartir disso que o for é mais útil ao utilizar uma ou mais variáveis, seria um pouco cansativo programar o mesmo código dentro do while;

int i=0;
int j=10;
while(i<5){
	i++;
}while(j>0){
	j--;
}

E se quiséssemos utilizar os whiles encadeados, teríamos que modificar um pouco o código;

int i=0;
int j=10;
while(j>0){
	while(i<5){
		i++;
	}j--;
}

Realmente, existem grandes diferenças between for e while =}, nesse caso, while seria uma opção inviável.
A propósito, acho que a dúvida do nosso amigo já está resolvida, vamos esperar uma resposta dele.

Então no C eu sei que ele conta até Mil mesmo sem nenhum código dentro do for, já no Java eu não sei ao certo.

Mas acho que pode ter as vantagens no C fazer isso, por isso C é uma das linguagens mais usadas para fazer malwares, daqueles que acaba com a memória e trava seu PC, agora o Java foi feito para evitar essas coisas, por que muitas veses alguem pode errar e fazer um codigo que vai travar o programa, como acontece com os ponteiros de C e C++, o java nem tem ponteiros explicitos por causa disso. Tente executar um for desses para ver se o java conta ou não.
Falou!!

O C só faz isso se você desabilitar todas as opções de otimização do compilador, o que é uma idiotice (por padrão, os compiladores usam o1 ou o2).
De maneira geral, deadcode elimination é uma estratégia de otimização bem simples e mesmo compiladores C muito rudimentares a implementam.

Não tem nada a ver. Alguns compiladores C são extremamente inteligentes, e extremamente otimizados e muitíssimo inteligentes. Especialmente os compiladores profissionais de mercado, como o Visual Studio e o GCC. Há, inclusive, compiladores específicos para aproveitar ao máximo certos compiladores, como é o caso do compilador da Intel.

As diferenças reais de performance ocorrem em outros campos:
a) Alocação de memória. Como foi falado ali, o Java utiliza garbage collection, dando ao programador apenas acesso indireto a memória. O algoritmo do garbage collector é bastante eficiente e “tunado” para aplicações comerciais de maneira geral. O C e o C++ utilizam alocação direta. Não há nenhuma estratégia inteligente na alocação direta, portanto, ela é pouquíssimo eficiente. Entretanto, ele dá a possibilidade de você usar memória stack diretamente (que é muito veloz) e dá a possibilidade de você implementar seu próprio alocador o que, apesar de difícil, pode ser bem mais otimizado do que o garbage collector jamais fará.

b) Compilação just-in-time: O código Java é compilado no momento da execução. Isso tem a vantagem do compilador poder usar instruções específicas da máquina para onde o programa java está executando. Como a compilação do C e do C++ é prévia, você não pode usar otimizações realmente agressivas sem limitar as plataformas de seu programa. Entretanto, a compilação just-in-time tem um custo para o Java. Ele precisa ficar constantemente analisando os métodos mais chamados (hotspots) e só então realizar essa compilação. Todo o processo tem impacto de performance em Runtime.

Há outros problemas a serem considerados:
a) O garbage collector é consome mais memória do que a alocação direta. Consideravelmente mais.
b) A execução do garbage collector congela o programa java por alguns microssegundos. Não é problema na maior parte de aplicações comerciais, mas é nas aplicações multimídia. Você nunca sabe quando o gc vai rodar.

Se quiser ler a fundo sobre como o java funciona, e entender melhor como os dois se comparam leia os artigos do Brian Goetz:

Tunning Garbage Collection With JVM 5: http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html

[quote=ViniGodoy]Outra situação bizarra do for é usa-lo com duas variáveis.

for(int i=0,int j=10; i &lt; 5 && j &gt; 0; i++ , j--) { }[/quote]

Não é bizarro se todo mundo se lembrar que

for (A; B; C) {
   d;
   e;
}

equivale sempre a:

{
    A;
    while (B) {
       d;
       e;
       C;
    }
}

No caso do exemplo do Vinigodoy (que a propósito tem só um errinho), o código equivalente tem apenas 1 (UM) while, não 2 como o Vynko achou.
O código corrigido do Vinigodoy é:

for(int i=0, j=10; i &lt; 5 && j &gt; 0; i++, j--) {  
    ...
}

Que é equivalente a:

{
    int i=0, j=10; 
    while (i &lt; 5 && j &gt; 0) {
       ...
       i++;
       j--;
    }
}

Sim, é por essas e outras que evito esse tipo de construção. Além de difícil de ler, não é usual.

Outra situação interessante do for é que ele não precisa necessariamente ser usado com variáveis numéricas:

for ( Iterator&lt;String&gt; it = exemplo.iterator(); it.hasNext(); ) { System.out.println( it.next() ); }

Eu sou bem conservador no uso do for. Geralmente só para o caso básico mesmo, com uma única variável contadora. Nem que isso gere um pouco mais de código.

Como o for é um while disfarçado, mas seu uso é sempre para percorrer alguma coleção, eu gosto de escrever o seguinte código:

BufferedReader br = new BufferedReader (new FileReader ("...."));
for (String linha = br.readLine(); linha != null; linha = br.readLine()) {
    ...
}

para enfatizar que estou percorrendo todas as linhas do arquivo, em vez de usar o código mais comum e que lembra código C (e que gera um readLine a menos, ha ha ha) :

BufferedReader br = new BufferedReader (new FileReader ("...."));
while ((linha = br.readLine()) != null) {
    ...
}

Não gosto muito de fazer atribuições dentro da condição de um while - fora o fato de que é muito C pro meu gosto, sempre há aquele maldito problema de escrever um “=” a mais ou a menos.

Se as pessoas aprenderem que “for” é para percorrer coleções, será fácil para elas transformarem seu código naquelas construções que são muito comuns em linguagens funcionais, como “map” ou “reduce” ou “apply” ou “flatten” ou “fold” ou “zip” - por exemplo, http://www.scala-lang.org/api/current/index.html#scala.collection.Map

Você errou uma coisa amigo, eu acho, o && faria com que quando o i se tornasse 5, o loop pararia, se estou correto… Mas por outro lado você está certo, utilizar o ||(invéz do &&) não teria necessidade nenhuma do meu patético código usando 2 whiles xD

Um improvável enriquecimento do assunto surgiu neste tópico no momento que passou-se a considerar otimizações de compilação. Muito bom :slight_smile: