Faz diferença se eu declarar variáveis ​​dentro ou fora de um loop em Java? [fechadas]

13

Possível duplicado:
onde você declara variáveis? O topo de um método ou quando você precisar deles?

Faz diferença se eu declarar variáveis ​​dentro ou fora de um loop em Java?

É isto

for(int i = 0; i < 1000; i++) {
   int temp = doSomething();
   someMethod(temp);
}

igual a isso (com relação ao uso de memória)?

int temp = 0;
for(int i = 0; i < 1000; i++) {
   temp = doSomething();
   someMethod(temp);
}

E se a variável temporária for, por exemplo, um ArrayList?

for(int i = 0; i < 1000; i++) {
   ArrayList<Integer> array = new ArrayList<Integer>();
   fillArray(array);
   // do something with the array
}

EDIT: com javap -ceu tenho a seguinte saída

Variável fora do loop:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iconst_0      
       3: istore_2      
       4: iload_2       
       5: sipush        1000
       8: if_icmpge     25
      11: invokestatic  #2                  // Method doSomething:()I
      14: istore_1      
      15: iload_1       
      16: invokestatic  #3                  // Method someMethod:(I)V
      19: iinc          2, 1
      22: goto          4
      25: return  

Variável dentro do loop:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: sipush        1000
       6: if_icmpge     23
       9: invokestatic  #2                  // Method doSomething:()I
      12: istore_2      
      13: iload_2       
      14: invokestatic  #3                  // Method someMethod:(I)V
      17: iinc          1, 1
      20: goto          2
      23: return        

E para os interessados, este código:

public class Test3 {
    public static void main(String[] args) {
        for(int i = 0; i< 1000; i++) {
            someMethod(doSomething());
        }   
    }
    private static int doSomething() {
        return 1;
    }
    private static void someMethod(int temp) {
        temp++;
    }
}

produz o seguinte:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: sipush        1000
       6: if_icmpge     21
       9: invokestatic  #2                  // Method doSomething:()I
      12: invokestatic  #3                  // Method someMethod:(I)V
      15: iinc          1, 1
      18: goto          2
      21: return   

Mas a otimização acontece no tempo de execução então. Existe uma maneira de analisar o código otimizado? (Desculpe pela edição longa)

Puckl
fonte
1
Estou satisfeito por você ter realmente visto a desmontagem e espero que tenha lhe ensinado algo. Eu esperava que alguém com experiência real em Java respondesse sua pergunta final sobre o código otimizado, mas talvez você possa postar essa parte específica no Stackoverflow - parece ser uma pergunta muito concreta.
Joris Timmermans
Sim, tentarei obter o código otimizado. (A questão mudou um pouco, pedi a coisa com o código otimizado na edição)
Puckl
Link quebrado no duplicado. É hora de fazer desta pergunta um original.
Zon

Respostas:

4

A resposta comum para a maioria dessas perguntas deve ser "por que você não tenta e descobre?". Em Java, você provavelmente poderia dar uma olhada no bytecode gerado (acredito que a ferramenta é chamada javap), para ver qual é a diferença no código de bytes entre essas duas maneiras de declarar a variável.

Fazer isso dessa maneira é uma experiência de aprendizado melhor para você, porque da próxima vez que estiver enfrentando um problema de otimização, você poderá usar a mesma ferramenta para verificar se o compilador está fazendo o que você espera - isso ajudará a evitar alterações desnecessárias na sua codificação estilo quando o otimizador funciona bem por conta própria ou encontrar ajustes reais quando você realmente precisa desse último desempenho.

Joris Timmermans
fonte
3

Resposta curta: não. Já havia perguntas semelhantes em algum lugar deste site. Não há diferença notável conforme o bytecode gerado. Declará-los quando necessário produz menos linhas de código

Aqui está a resposta aceita: /software//a/56590/43451

Kemoda
fonte
E o desempenho quando você cria um novo objeto dentro do loop, que também poderia ser criado apenas uma vez?
Bubblewrap
3
Nesse caso, obviamente há penalidade de desempenho e memória. Mas não é bem o caso em questão da op
Kemoda
1
Link quebrado.
Zon
1

No nível da variável individual, não há diferença significativa na eficiência, mas se você tivesse uma função com 1000 loops e 1000 variáveis ​​(não importa o estilo ruim implícito), poderia haver diferenças sistêmicas, porque toda a vida de todas as variáveis ​​seria o mesmo em vez de sobreposto. Isso pode afetar coisas como o tamanho da pilha e a capacidade do coletor de lixo de limpar as variáveis ​​que estavam sendo mantidas vivas por mais tempo do que o necessário.

Além disso, é um estilo muito melhor fornecer às variáveis ​​o menor escopo possível. Previne acidentes.

ddyer
fonte
Isso não é verdade - no nível da JVM, não existe escopo limitado para variáveis ​​locais.
Michael Borgwardt
quer dizer que se eu escrever para (int i = ..) 1000 vezes, haverá 1000 variáveis ​​diferentes na pilha quando sair da função?
Dller
de acordo com artima.com/insidejvm/ed2/jvm8.html "Por exemplo, se duas variáveis ​​locais têm escopos limitados que não se sobrepõem, como as variáveis ​​locais iej no Exemplo3b, os compiladores podem usar a mesma entrada de matriz para ambas as variáveis. "E isso só faz sentido, os compiladores são livres para otimizar o tamanho do quadro da pilha dessa maneira.
Ddyer 8/10
1
Bom ponto; mas, se estivermos falando de otimizações do compilador, o compilador pode reutilizar quase com facilidade as entradas de variáveis ​​locais para variáveis ​​com escopo lexical sobreposto, mas que não são usadas de maneira sobreposta.
22812 Michael Borgwardt