Sisäkkäinen luokka on luokka, joka on määritelty toisen luokan sisällä. Javassa on neljä lajia — staattinen sisäkkäinen, sisä (ei-staattinen), paikallinen ja anonyymi — jokaisella on erilainen pääsy liittyvän luokan sisälle ja erilaiset käyttötarkoitukset.
1. Staattinen sisäkkäinen luokka — riippumaton instanssista
public class Outer {
private static int data = 10;
static class Nested { // static → no reference to an Outer INSTANCE
void show() {
System.out.println(data); // can access static members of Outer only
}
}
}
Outer.Nested n = new Outer.Nested(); // created without an Outer instance
static-sisäkkäinen luokka käyttäytyy kuin ylimmän tason luokka, mutta on nimetyn ulomman luokan sisällä. Se ei pidä viitettä ulommalle instanssille — käytetään apuluokkien ryhmittelyyn (esim. Builder, Node tietorakenteessa).
2. Sisäluokka (ei-staattinen) — sidottu instanssiin
public class Outer {
private int value = 5;
class Inner { // non-static → has an implicit reference to Outer
void show() {
System.out.println(value); // can access Outer's INSTANCE members (even private)
}
}
}
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // needs an Outer instance to create
Ei-staattinen sisäluokka pitää implisiittistä viitettä liittyvään instanssiinsa, joten se pääsee käsiksi ulomman objektin instanssikenttiin. (Varoitus: tämä viite voi aiheuttaa muistivuotoja, jos sisäinen instanssi elää pidempään kuin ulompi.)
3. Paikallinen luokka — määritelty metodin sisällä
void process() {
class Helper { // local to this method
void run() { ... }
}
new Helper().run();
}
Harvinainen; rajautunut metodiin.
4. Anonyymi luokka — kertakäyttöinen toteutus, ei nimeä
// implement an interface/abstract class inline, for single use
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { handleClick(); }
});
Runnable task = new Runnable() {
public void run() { System.out.println("running"); }
};
Anonyymi luokka on kertaiskuinen toteutus rajapinnasta tai luokasta, määritelty ja instantioitu kerralla — historiallisesti yleinen tapahtumankäsittelijöille ja takaisinkutsuille. Moderni Java korvaa nämä usein lambdoilla, kun kohde on funktionaalinen rajapinta:
button.addActionListener(e -> handleClick()); // ✅ lambda — much cleaner
Runnable task = () -> System.out.println("running");
Miksi sillä on merkitystä
Sisäkkäiset luokat ovat hyödyllinen työkalu luokkien loogiselle ryhmittelylle, joita käytetään vain yhdessä yhteydessä, mikä lisää kapselointia ja luettavuutta.
Lajien ymmärtäminen — erityisesti staattinen-vai-sisä-erottelu (staattinen = riippumaton, sisä = pitää viitettä liittyvään instanssiin) — on tärkeä sekä suunnittelulle että virheiden välttämiselle: sisäluokkien implisiittiviite voi aiheuttaa muistivuotoja, ja valitseminen staattinen, kun et tarvitse ulompaa instanssia, on siistimpi oletusarvo.
Anonyymit luokat olivat klassinen tapa tarjota sisäisiä toteutuksia (tapahtumankäsittelijät, vertailijat), ja tieto siitä, että lambdat korvaavat ne suurelta osin funktionaalisille rajapinnoille, heijastaa modernia Java-sujuvuutta.
Nämä esiintyvät koko standardi-kirjastossa (esim. Map.Entry on sisäkkäinen rajapinta, rakentajat ovat staattisia sisäkkäisiä luokkia), mikä tekee niistä käytännöllisiä, usein kohdattuja tietoja.
