Non riesco a capire questi pezzi di codice:
codice:
public interface FiltroFilm
{
    boolean filtra(Film film);
}
Ok, una classe anonima può o estendere una classe o implementare una interfaccia. In questo caso è evidente che deve implementare una interfaccia, ma perchè si sceglie di implementare una interfaccia piuttosto che usare una classe ed estenderla?

codice:
public Film[] getFilmFiltrati(FiltroFilm filtroFilm) {
        Film [] filmFiltrati = new Film[10];
        for (int i = 0, j= 0; i< 10;i++) {
            if (filtroFilm.filtra(films[i])) {
                filmFiltrati[j] = films[i];
                j++;
            }
        }
        return filmFiltrati;
}
In questo caso non capisco cosa fa questo metodo. Dovrebbe restituire i film filtrati, ma in base a che criterio?

codice:
Film[] filmDiFantascienza = videoteca.getFilmFiltrati(new FiltroFilm() {
                public boolean filtra(Film film) {
                return"Fantascienza".equals(film.getGenere());
                }
          } );
codice:
Film[] beiFilms =  videoteca.getFilmFiltrati(new FiltroFilm() {
                public boolean filtra(Film film) {
                return film.getMediaRecensioni() >3;
                }
          } );
I due pezzi di codice di sopra invece sono la parte principale del dubbio perchè rappresentano appunto le classi anonime.
Ho capito che la sintassi deve essere del tipo:
codice:
FiltroFilm filtro = new FiltroFilm() {
             public boolean filtra(Film film)
             {
                ...
             }
         };
e che volendo si può passare questa classe anonima come input ad un metodo (come accade con getFilmFiltrati).
Quello che però non capisco è cosa realmente accade in quelle righe di codice, in modo particolare il metodo filtra restituisce un booleano. E allora cosa fa quel codice? Passa un booleano al metodo getFilmFiltrati?
Insomma mi sfugge la logica di questi pezzi di codice.