Klasy lokalne i anonimowe
Deklaruj klasy wewnątrz metod i twórz w locie anonimowe implementacje interfejsów.
Klasy lokalne i anonimowe to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.
Klasy lokalne i anonimowe
Klasy lokalne są definiowane wewnątrz metody. Klasy anonimowe to klasy lokalne bez nazwy — łączą deklarację klasy z jej utworzeniem. Oba rodzaje przechwytują lokalne zmienne, które są efektywnie finalne.
Deklarowanie klasy lokalnej
Klasa lokalna jest deklarowana wewnątrz ciała metody. Może uzyskiwać dostęp do składowych klasy otaczającej oraz do lokalnych zmiennych, które są efektywnie finalne.
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, AliceZmienne efektywnie finalne
Klasy lokalne i anonimowe mogą przechwytywać wyłącznie lokalne zmienne, które są efektywnie finalne — po inicjalizacji nie są nigdy ponownie przypisywane.
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
}Podstawy klas anonimowych
Klasa anonimowa implementuje interfejs lub rozszerza klasę bezpośrednio, w jednym wyrażeniu.
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]Klasa anonimowa a lambda
W przypadku interfejsów z jedną metodą abstrakcyjną (SAM) lambdy zastępują klasy anonimowe. Klasy anonimowe są nadal potrzebne w przypadku interfejsów z wieloma metodami lub przy rozszerzaniu klas abstrakcyjnych.
// 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 shorthandKlasa anonimowa ze stanem
Klasy anonimowe mogą mieć pola, w przeciwieństwie do lambd. Jest to przydatne, gdy trzeba przechowywać stan wewnątrz anonimowej implementacji.
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()); // 2Wzorzec anonimowego nasłuchiwacza
Przed wprowadzeniem lambd klasy anonimowe były standardowym rozwiązaniem dla nasłuchiwaczy zdarzeń w programowaniu graficznych interfejsów użytkownika i aplikacji 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!"));Klasa lokalna dla złożonej logiki
Klasy lokalne sprawdzają się, gdy potrzebujesz klasy z wieloma metodami tylko w jednym miejscu — gdy rozwiązanie jest zbyt złożone dla lambdy, ale zbyt specyficzne dla klasy najwyższego poziomu.
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]Klasa anonimowa dla klasy abstrakcyjnej
Klasy anonimowe mogą rozszerzać klasy abstrakcyjne, przesłaniając metody abstrakcyjne bez tworzenia nazwanej podklasy.
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")));Antywzorzec inicjalizacji z podwójnymi klamrami
Technika inicjalizacji z podwójnymi klamrami używa klas anonimowych do inicjalizowania kolekcji. Tworzy podklasę z inicjalizatorem instancji. Należy jej unikać — jest nieefektywna i podatna na błędy.
// 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));Wybór: lambda, klasa anonimowa czy lokalna
Wskazówki dotyczące wyboru:
- Lambda: jedna metoda abstrakcyjna, brak dodatkowego stanu, brak dziedziczenia
- Klasa anonimowa: wiele metod, potrzeba przechowywania stanu lub rozszerzanie klasy abstrakcyjnej
- Klasa lokalna: potrzeba ponownego użycia w obrębie metody, wiele metod, złożony stan
Szybkie sprawdzenie
Co klasa anonimowa zawsze robi w jednym wyrażeniu?
Podsumowanie: klasy lokalne i anonimowe
Najważniejsze informacje:
- Klasy lokalne są definiowane wewnątrz metod i mogą uzyskiwać dostęp do lokalnych zmiennych, które są efektywnie finalne
- Klasy anonimowe łączą deklarację klasy z jej utworzeniem w jednym wyrażeniu
- Klasy anonimowe mogą mieć pola i wiele metod — w przeciwieństwie do lambd
- Lambdy zastępują klasy anonimowe w przypadku interfejsów z jedną metodą abstrakcyjną
- Używaj klas lokalnych, gdy logika jest wystarczająco złożona, by wymagać klasy, ale specyficzna dla jednej metody
- Unikaj inicjalizacji z podwójnymi klamrami — tworzy niepotrzebne anonimowe podklasy
Często zadawane pytania
Czy lekcja „Klasy lokalne i anonimowe” jest bezpłatna?
Tak — pełny tekst „Klasy lokalne i anonimowe” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Klasy lokalne i anonimowe”?
Deklaruj klasy wewnątrz metod i twórz w locie anonimowe implementacje interfejsów. Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Java Academy?
Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Klasy lokalne i anonimowe”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?
Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Statyczne klasy zagnieżdżone
- Klasy wewnętrzne i dostęp do klasy zewnętrznej
- Klasy lokalne i anonimowe
- Wybór właściwej strategii zagnieżdżania