Hola!
Estuve haciendo la prueba de ver qué sucedía cuando usamos el for-each para recorrer un objeto tipo ConjuntoPersonas, y es cierto lo que dice Lorenzo31.
Si corremos paso-por-paso el código Programa nos damos cuenta que al entrar en la instrucción for (del for-each) se llama al método iterator() de la clase ConjuntoPersonas.
Por lo tanto for-each utiliza el método iterator() de la clase ConjuntoPersonas, de la misma manera que si utilizáramos un iterador sobre el objeto ConjuntoPersonas y luego llamáramos a sus métodos hasNext() y Next().
Es decir, que la utilización de los métodos declarados en la clase concreta MiIteratorPersona (que son los métodos que estamos obligados a implementar de la interface Iterator) son utilizados de la misma manera tanto al hacer en nuestro código Programa:
Iterator<Persona> it1 = cp.iterator();
while (it1.hasNext()){
Persona tmp = it1.next();
System.out.println("La persona:"+tmp.dni+" tiene una edad de:"+tmp.edad);
}
como si hiciéramos :
for (Persona p : cp) // Esto es un for extendido o for-each{
System.out.println("La persona:"+p.dni+" tiene una edad de:"+p.edad);
}
Es como si (y por favor que se tome bien el entrecomillado) "el for-each fuese una máscara del iterador", ambas cosas funcionalmente hacen lo mismo.
Otro dato importante que va en el mismo sentido: no podríamos usar for-each para un objeto tipo ConjuntoPersonas si ConjuntoPersonas no implementara la interfaz Iterable.
Una forma simple de hacer saltar esto sería: haciendo un cambio en una línea de la clase ConjuntoPersonas:
public class ConjuntoPersonas implements Iterable<Persona>{
por:
public class ConjuntoPersonas {
(y si ningún otro cambio más en el código). Al compilar la clase Persona nos da un error de compilación en el for-each con la siguiente leyenda:
for-each not applicable to expression type
required: array or java.lang.Iterable; found: ConjuntoPersonas