0Pricing
Java Academy · Lezione

Classi locali e anonime

Dichiari classi all'interno dei metodi e crei al volo implementazioni anonime di interfacce.

Classi locali e anonime è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.

Classi locali e anonime

Le classi locali sono definite all'interno di un metodo. Le classi anonime sono classi locali senza nome: combinano la dichiarazione della classe e la sua istanziazione. Entrambe catturano le variabili locali effettivamente finali.

Dichiarazione di una classe locale

Una classe locale viene dichiarata all'interno del corpo di un metodo. Può accedere ai membri della classe che la contiene e alle variabili locali effettivamente finali.

static void greet(String language) {
    // Local class — defined inside the method
    class Greeter {
        String sayHello(String name) {
            // Can access 'language' — it is effectively final
            return switch (language) {
                case "EN" -> "Hello, " + name;
                case "ES" -> "Hola, " + name;
                case "FR" -> "Bonjour, " + name;
                default   -> "Hi, " + name;
            };
        }
    }

    Greeter g = new Greeter();
    System.out.println(g.sayHello("Alice"));
}
greet("ES"); // Hola, Alice

Variabili effettivamente finali

Le classi locali e anonime possono catturare solo variabili locali effettivamente finali, cioè variabili a cui non viene mai riassegnato un valore dopo l'inizializzazione.

void process(int threshold) {
    // threshold is effectively final (never reassigned)
    Runnable r = new Runnable() {
        public void run() {
            System.out.println("Threshold: " + threshold);
        }
    };
    r.run();

    // threshold = 10; // If you add this, the anonymous class won't compile
}

Nozioni di base sulle classi anonime

Una classe anonima implementa un'interfaccia o estende una classe direttamente, all'interno di una singola espressione.

interface Comparator<T> {
    int compare(T a, T b);
}

// Anonymous class implementing Comparator
java.util.Comparator<String> byLength = new java.util.Comparator<String>() {
    @Override
    public int compare(String a, String b) {
        return Integer.compare(a.length(), b.length());
    }
};

List<String> words = new ArrayList<>(List.of("banana", "fig", "apple", "kiwi"));
words.sort(byLength);
System.out.println(words); // [fig, kiwi, apple, banana]

Classi anonime e lambda

Per le interfacce a singolo metodo astratto (SAM), le lambda sostituiscono le classi anonime. Le classi anonime sono comunque necessarie per le interfacce con più metodi o quando si estendono classi astratte.

// Anonymous class for single-method interface
Runnable r1 = new Runnable() {
    public void run() { System.out.println("Running!"); }
};

// Lambda — cleaner for SAM interfaces
Runnable r2 = () -> System.out.println("Running!");

// Must use anonymous class for multi-method interface:
java.io.FilenameFilter filter = new java.io.FilenameFilter() {
    public boolean accept(java.io.File dir, String name) {
        return name.endsWith(".java");
    }
}; // FilenameFilter is not a SAM — no lambda shorthand

Classe anonima con stato

Le classi anonime possono avere campi, a differenza delle lambda. Sono utili quando è necessario mantenere uno stato all'interno dell'implementazione anonima.

interface Counter { int increment(); int get(); }

Counter counter = new Counter() {
    private int count = 0;

    public int increment() { return ++count; }
    public int get()       { return count; }
};

System.out.println(counter.increment()); // 1
System.out.println(counter.increment()); // 2
System.out.println(counter.get());       // 2

Pattern dei listener anonimi

Prima delle lambda, le classi anonime erano il pattern standard per i listener di eventi nella programmazione GUI e Android.

// Modern Android/Swing style: anonymous class listener
Button loginButton = new Button(); // hypothetical
loginButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick() {
        System.out.println("Login button clicked!");
    }
});

// Modern equivalent with lambda (if OnClickListener is SAM):
loginButton.setOnClickListener(() -> System.out.println("Clicked!"));

Classe locale per una logica complessa

Le classi locali sono adatte quando è necessaria una classe con più metodi in un unico punto: una situazione troppo complessa per una lambda, ma troppo specifica per una classe di primo livello.

static List<String> processData(List<String> data, String prefix) {
    // Local class: complex enough for a class, used only here
    class DataProcessor {
        List<String> result = new ArrayList<>();

        void process(String item) {
            // prefix is effectively final
            if (item.startsWith(prefix)) {
                result.add(item.toUpperCase());
            }
        }
    }
    DataProcessor dp = new DataProcessor();
    data.forEach(dp::process);
    return dp.result;
}
System.out.println(processData(List.of("apple","avocado","banana"), "a"));
// [APPLE, AVOCADO]

Classe anonima per una classe astratta

Le classi anonime possono estendere classi astratte, eseguendo l'override dei metodi astratti senza creare una sottoclasse con nome.

abstract class ReportFormatter {
    abstract String formatHeader(String title);
    abstract String formatBody(List<String> rows);

    String format(String title, List<String> rows) {
        return formatHeader(title) + "\n" + formatBody(rows);
    }
}

ReportFormatter csvFormatter = new ReportFormatter() {
    public String formatHeader(String t) { return "\"" + t + "\""; }
    public String formatBody(List<String> rows) {
        return String.join("\n", rows);
    }
};
System.out.println(csvFormatter.format("Sales", List.of("a,1","b,2")));

Anti-pattern dell'inizializzazione a doppia graffa

Il trucco dell'inizializzazione a doppia graffa utilizza classi anonime per inizializzare le raccolte. Crea una sottoclasse con un inizializzatore di istanza. È opportuno evitarlo: è inefficiente e soggetto a errori.

// Anti-pattern: double-brace initialization
Map<String, Integer> map = new HashMap<String, Integer>() {{
    put("a", 1);
    put("b", 2);
}};
// Creates an anonymous HashMap subclass — wasteful!

// GOOD: use Map.of() or Map.ofEntries()
Map<String, Integer> better = Map.of("a", 1, "b", 2);

// Or a mutable map:
Map<String, Integer> mutable = new HashMap<>(Map.of("a", 1, "b", 2));

Scelta: lambda, classe anonima o classe locale

Guida alla scelta:

  • Lambda: un singolo metodo astratto, nessuno stato aggiuntivo, nessuna ereditarietà
  • Classe anonima: più metodi, necessità di mantenere uno stato o estensione di una classe astratta
  • Classe locale: necessità di riutilizzo all'interno del metodo, più metodi, stato complesso

Verifica rapida

Che cosa fa sempre una classe anonima in una singola espressione?

Riepilogo: classi locali e anonime

Punti chiave:

  • Le classi locali sono definite all'interno dei metodi e possono accedere alle variabili locali effettivamente finali
  • Le classi anonime combinano la dichiarazione della classe e la sua istanziazione in una singola espressione
  • Le classi anonime possono avere campi e più metodi, a differenza delle lambda
  • Le lambda sostituiscono le classi anonime per le interfacce a singolo metodo astratto
  • Utilizzare le classi locali quando la logica è abbastanza complessa da richiedere una classe, ma specifica per un solo metodo
  • Evitare l'inizializzazione a doppia graffa: crea sottoclassi anonime non necessarie

Domande Frequenti

La lezione «Classi locali e anonime» è gratuita?

Sì — il testo completo di «Classi locali e anonime» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.

Cosa imparerò in «Classi locali e anonime»?

Dichiari classi all'interno dei metodi e crei al volo implementazioni anonime di interfacce. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Java Academy?

Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Classi locali e anonime»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Java Academy?

Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Classi annidate statiche
  2. Classi interne e accesso alla classe esterna
  3. Classi locali e anonime
  4. Scegliere la strategia di annidamento più adatta
← Torna a Java Academy