Olá Gabriel!
Cada valor de 'i' referência um dos índices do array (que sendo tamanho cinco, começa em zero e vai até quatro).
'length' é um atributo do array criado e será sempre equivalente ao tamanho do array (neste caso cinco). Como os índices vão de zero a quatro, não pode na laçada ser 'menor ou igual' ao length do array ou será lançada uma ArrayIndexOutOfBoundsException.
A atribuição idades[i] = i * i e o System.out.println poderiam ter ficado em uma mesma laçada. Ou seja, ao atribuir já imprimiria no console o valor da respectiva posição.
Acredito que o instrutor fez dois laços para dividir as responsabilidades da atribuição e da impressão no array, tornando assim mais fácil o entendimento. Mas como disse acima, as instruções poderiam ter ficado em um mesmo laço.
Espero ter esclarecido sua dúvida (: