Certo, vamos lá…
O seu foreach está retornando o valor dos elementos do array 1 a 1.
seu array é
0 | 1 | 2 | 3 //Posições
1 | 2 | 3 | 4 //Valores
Na primeira passagem o valor de i é o valor na posição 0 do array, que executa o código:
arr[1] =0;
Então os valores do seu array passam a ser:
0 | 1 | 2 | 3 //Posições
1 | 0 | 3 | 4 //Valores
Na segunda passagem o valor de i será o valor da posição 1, executando o código:
arr[0] = 0;
Então os valores do seu array passam a ser:
0 | 1 | 2 | 3 //Posições
0 | 0 | 3 | 4 //Valores
Na tereceira passagem o valor de i será o valor da posição 2, executando o código:
arr[3] = 0;
Então os valores do seu array passam a ser:
0 | 1 | 2 | 3 //Posições
0 | 0 | 3 | 0 //Valores
Na última passagem do for each o valor de i passa a ser o valor da posição 3 do array, executando novamente o código:
arr[0] = 0;
O que não modifica os valores do seu array, já que o primeiro valor já era 0.
Então os valores do seu array assim que o for each acaba de ser executado é:
0 | 1 | 2 | 3 //Posições
0 | 0 | 3 | 0 //Valores
Questões de certificaão são na maioria das vezes pegadinhas… Na primeira olhada que dei neste código eu pensei que o resultado seria um erro de execução pois na última passagem no for each ele lançaria um ArrayIndexOutOfBoundsException
Abs espero que tenha entendido o que acontece no código.