ローカル変数は、通常 (最適化されていない限り) スタック メモリに保持されます。ただし、プリミティブ値または参照のみを格納できます。参照されるオブジェクト自体は通常、ヒープに割り当てられます (JIT 最適化に関係なく)。
スタック ベースのメモリ割り当て (ウィキペディア)とヒープベースのメモリ割り当て (ウィキペディア)を参照してください。
スタックに値を格納するのは非常に安価です。関数呼び出しと同様に、リターン ポインターをスタックに格納します。スタック ポインタをインクリメントするだけで済みます (専用の CPU レジスタをインクリメントするのは高速であることが想像できます!)。
オブジェクト自体が異なります。理論的には、次の反復では値が不要であることを明確に示しているため、一部の Java コンパイラまたは JIT は 2 番目のコードをより適切に最適化できる可能性があることに注意してください。(さらに優れたコンパイラは、これ自体を理解できるはずです。)
一般に、最新のコンパイラは、どちらの場合も最適化後に同じマシン コードを生成する必要があります。(これは JIT コンパイラで発生する可能性があるため、Java バイトコードは依然として違いを示す可能性があります)。
とにかく、ローカル変数を再利用して過度に最適化しようとしないでください。代わりに、明示的なコードを記述し、コンパイラに最適化させます。ループ内で新鮮な変数を使用することにより、どこでも再利用されないことを明示します。これにより、プログラミング エラーを防ぐことができます。