Java: instanciar variables ​​em loop: estilo bom ou ruim?

Eu tenho uma pergunta simples. Normalmente escrevo código assim:

String myString = "hello"; for (int i=0, i<10; i++) { myString = "hello again"; } 

Porque eu acho que o seguinte não seria um bom estilo, pois criaria muitos objects desnecessários.

 for (int i=0, i<10; i++) { String myString = "hello again"; } 

Isso está correto? Ou isso é apenas o caso quando eu tenho um object explícito como um object de uma class que criei? E se fosse um booleano ou um int? Qual é o melhor estilo de codificação? Instanciá-lo uma vez antes do loop e usá-lo no loop ou instanciá-lo todas as vezes no loop novamente? E porque? Porque o programa é mais rápido ou menos armazenamento é usado ou …?

Alguém me disse que, se fosse um booleano, eu deveria instanciá-lo diretamente no loop. Ele disse que não faria diferença para o heap e seria mais claro que a variável pertence ao loop. Então, o que está correto?

Obrigado por uma resposta! 🙂

====

Obrigado por todas as suas respostas!

Em conclusão: é preferível declarar um object dentro do menor escopo possível. Não há melhorias de desempenho declarando e instanciando objects fora do loop, mesmo se em todo looping o object for reinstanciado.

Não, o último código não é realmente válido. Seria com chaves embora:

 for (int i=0; i<10; i++) { String myString = "hello again"; } 

(Basicamente você não pode usar uma declaração de variável como um corpo de declaração única para uma instrução if , um loop etc.)

Seria inútil, mas válido - e preferível à primeira versão, IMO. Não é preciso mais memory, mas geralmente é uma boa idéia dar às variables ​​locais o escopo mais curto possível, declarando o mais tarde possível, idealmente inicializando no mesmo ponto. Isso deixa mais claro onde cada variável pode ser usada.

Claro, se você precisar se referir à variável fora do loop (antes ou depois), então você precisará declará-la fora do loop também.

Você precisa diferenciar entre variables e objects quando considera a eficiência. O código acima usa no máximo um object - o object String referido pelo literal "hello again".

Como Binyamin Sharet mencionou, você geralmente deseja declarar uma variável dentro do menor escopo possível. Em seus exemplos específicos, o segundo é geralmente preferível, a menos que você precise acessar a variável fora de seu loop.

No entanto, sob certas condições, isso pode ter implicações no desempenho – ou seja, se você estiver instanciando o mesmo object repetidamente. Em seu exemplo específico, você se beneficia do pool automático de literais String do Java. Mas suponha que você estivesse realmente criando uma nova instância do mesmo object em cada iteração do loop, e esse loop estava sendo executado centenas ou milhares de vezes:

 for (int i=0, i<1000; i++) { String myString = new String("hello again"); // 1000 Strings are created--one on every iteration ... } 

Se o seu loop está fazendo loop centenas ou milhares de vezes, mas acontece que você está instanciando o mesmo object repetidamente, instanciando-o dentro do loop resultará em muita garbage collection desnecessária, porque você cria e lança afastado um novo object em cada iteração. Nesse caso, seria melhor declarar e instanciar a variável uma vez fora do loop:

 String myString = new String("hello again"); // only one String is created for (int i=0, i<1000; i++) { ... } 

E, para fazer um círculo completo, você pode limitar manualmente o escopo adicionando chaves extras ao redor da seção relevante do código:

 { // Limit the scope String myString = new String("hello again"); for (int i=0, i<1000; i++) { ... } } 

Parece que você quer dizer declare , não instantiate e, em geral, você deve declarar uma variável no menor escopo necessário (neste caso – no loop).

Se você for usar a variável fora do loop for, então declare-a, ou então é melhor manter o escopo no mínimo.

O problema com o segundo é que você cria um object e alguém (o GC) tem que limpá-lo, é claro que por 10 iterações ele não é importante.

BTW no seu exemplo específico eu teria escrito

  String myString = null; final String HELLO_AGAIN="hello again"; for (int i=0; i<10; i++) myString = HELLO_AGAIN; 

A menos que o valor seja alterado, você deve definitivamente instanciar fora do loop.

O problema aqui é que String é um object imutável: você não pode alterar o valor de uma string, somente você pode criar novos objects String. De qualquer maneira, se seu objective é atribuir uma variável a uma nova instância de object, limite seu escopo e declare-o dentro do corpo de seu loop.

Se o seu object é mutável, então seria razoável reutilizar o object em cada próxima iteração do loop e apenas alterar os atributos que você precisa. Esse conceito é usado para executar a mesma consulta várias vezes, mas com parâmetros diferentes, você usa um PreparedStatement.

No caso extremo, você ainda manteria pools de objects que podem ser compartilhados em todo o aplicativo. Você cria objects adicionais à medida que você fica sem resources, você diminui se detectar uma quantidade razoável de não uso. Esse conceito é usado para manter um pool de conexões.

Intereting Posts