Java Academy · Oppitunti

Paikalliset ja anonyymit luokat

Määritä luokkia metodien sisällä ja luo rajapintojen anonyymeja toteutuksia tarpeen mukaan.

Oppitunti 3/413 vaihetta

Paikalliset ja anonyymit luokat on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.

Paikalliset ja anonyymit luokat

Paikalliset luokat määritellään metodin sisällä. Anonyymit luokat ovat nimettömiä paikallisia luokkia — ne yhdistävät luokan määrittelyn ja ilmentämisen. Molemmat voivat kaapata käytännössä final olevia paikallisia muuttujia.

Paikallisen luokan määrittely

Paikallinen luokka määritellään metodin rungon sisällä. Se voi käyttää ympäröivän luokan jäseniä ja käytännössä final olevia paikallisia muuttujia.

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

Käytännössä final olevat muuttujat

Paikalliset ja anonyymit luokat voivat kaapata vain käytännössä final olevia paikallisia muuttujia — niitä ei määrittämisen jälkeen koskaan sijoiteta uudelleen.

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
}

Anonyymien luokkien perusteet

Anonyymi luokka toteuttaa rajapinnan tai perii luokan suoraan yhdessä lausekkeessa.

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]

Anonyymi luokka ja lambda

Yhden abstraktin metodin (SAM) rajapinnoissa lambdat korvaavat anonyymit luokat. Anonyymeja luokkia tarvitaan edelleen useita metodeja sisältäville rajapinnoille tai abstrakteja luokkia laajennettaessa.

// 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

Tilaa sisältävä anonyymi luokka

Anonyymeilla luokilla voi olla kenttiä, toisin kuin lambdoilla. Tästä on hyötyä, kun anonyymin toteutuksen sisällä on säilytettävä tilaa.

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

Anonyymin kuuntelijan malli

Ennen lambdoja anonyymit luokat olivat graafisten käyttöliittymien ja Android-ohjelmoinnin vakiomalli tapahtumankuuntelijoille.

// 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!"));

Paikallinen luokka monimutkaista logiikkaa varten

Paikalliset luokat sopivat tilanteisiin, joissa tarvitsette useita metodeja sisältävän luokan vain yhdessä paikassa — logiikka on lambdalle liian monimutkaista mutta ylätason luokalle liian erityistä.

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]

Anonyymi luokka abstraktille luokalle

Anonyymit luokat voivat laajentaa abstrakteja luokkia ja ylikirjoittaa abstraktit metodit ilman nimettyä aliluokkaa.

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")));

Kaksoisaaltosulkeiden alustuksen vastainen malli

Kaksoisaaltosulkeiden alustustemppu käyttää anonyymeja luokkia kokoelmien alustamiseen. Se luo aliluokan, jossa on instanssin alustuslohko. Välttäkää sitä — se on tehoton ja altis virheille.

// 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));

Valinta: lambda, anonyymi vai paikallinen luokka

Ohje valintaan:

  • Lambda: yksi abstrakti metodi, ei ylimääräistä tilaa eikä perintää
  • Anonyymi luokka: useita metodeja, tarve tilalle tai abstraktin luokan laajentaminen
  • Paikallinen luokka: uudelleenkäyttö metodin sisällä, useita metodeja tai monimutkainen tila

Pikatarkistus

Mitä anonyymi luokka tekee aina yhdessä lausekkeessa?

Kertaus: paikalliset ja anonyymit luokat

Tärkeimmät opit:

  • Paikalliset luokat määritellään metodien sisällä, ja ne voivat käyttää käytännössä final olevia paikallisia muuttujia
  • Anonyymit luokat yhdistävät luokan määrittelyn ja ilmentämisen yhteen lausekkeeseen
  • Anonyymeilla luokilla voi olla kenttiä ja useita metodeja — toisin kuin lambdoilla
  • Lambdat korvaavat anonyymit luokat yhden abstraktin metodin rajapinnoissa
  • Käyttäkää paikallisia luokkia, kun logiikka on luokalle riittävän monimutkaista mutta koskee vain yhtä metodia
  • Välttäkää kaksoisaaltosulkeiden alustusta — se luo tarpeettomia anonyymeja aliluokkia
Aloita maksutta

Opi Java tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
104
Oppitunnit
374

Usein kysytyt kysymykset

Onko oppitunti ”Paikalliset ja anonyymit luokat” ilmainen?

Kyllä – oppitunnin ”Paikalliset ja anonyymit luokat” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Paikalliset ja anonyymit luokat”?

Määritä luokkia metodien sisällä ja luo rajapintojen anonyymeja toteutuksia tarpeen mukaan. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”Paikalliset ja anonyymit luokat”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?

Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Staattiset sisäkkäiset luokat
  2. Sisäluokat ja ympäröivän luokan käyttö
  3. Paikalliset ja anonyymit luokat
  4. Sopivan sisäkkäisyysstrategian valitseminen
← Takaisin: Java Academy