class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
Disse interne klassene kalles nestede. De er delt inn i 2 typer:
- Ikke-statiske nestede klasser. Disse kalles også indre klasser.
- Statiske nestede klasser.
- en lokal klasse
- en anonym klasse

public class Bicycle {
private String model;
private int weight;
public Bicycle(String model, int weight) {
this.model = model;
this.weight = weight;
}
public void start() {
System.out.println("Let's go!");
}
public class Handlebar {
public void right() {
System.out.println("Steer right!");
}
public void left() {
System.out.println("Steer left!");
}
}
public class Seat {
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
}
Her har vi Bicycle
klassen. Den har 2 felt og 1 metode: start()
. 
Handlebar
og Seat
. Koden deres er skrevet inne i Bicycle
klassen. Dette er fullverdige klasser: som du kan se, har hver av dem sine egne metoder. På dette tidspunktet har du kanskje et spørsmål: hvorfor i all verden skulle vi sette en klasse inn i en annen? Hvorfor gjøre dem til indre klasser? Vel, anta at vi trenger separate klasser for konseptene styre og sete i programmet vårt. Det er selvfølgelig ikke nødvendig for oss å lage dem nestet! Vi kan lage vanlige klasser. For eksempel slik:
public class Handlebar {
public void right() {
System.out.println("Steer right!");
}
public void left() {
System.out.println("Steer left");
}
}
public class Seat {
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
Veldig godt spørsmål! Selvfølgelig er vi ikke begrenset av teknologien. Å gjøre det er absolutt et alternativ. Her er det viktige mer riktig utforming av klassene fra perspektivet til et spesifikt program og dets formål. Indre klasser er for å skille ut en enhet som er uløselig forbundet med en annen enhet. Styre, seter og pedaler er komponenter i en sykkel. Atskilt fra sykkelen gir de ikke mye mening. Hvis vi gjorde alle disse konseptene separate offentlige klasser, ville vi hatt koden slik i programmet vårt:
public class Main {
public static void main(String[] args) {
Handlebar handlebar = new Handlebar();
handlebar.right();
}
}
Hmm... Betydningen av denne koden er til og med vanskelig å forklare. Vi har et vagt styre (hvorfor er det nødvendig? Ingen anelse, for å være ærlig). Og dette håndtaket svinger til høyre... helt av seg selv, uten sykkel... av en eller annen grunn. Ved å skille konseptet med styret fra konseptet med sykkelen, mistet vi litt logikk i programmet vårt. Ved å bruke en indre klasse ser koden veldig annerledes ut:
public class Main {
public static void main(String[] args) {
Bicycle peugeot = new Bicycle("Peugeot", 120);
Bicycle.Handlebar handlebar = peugeot.new Handlebar();
Bicycle.Seat seat = peugeot.new Seat();
seat.up();
peugeot.start();
handlebar.left();
handlebar.right();
}
}
Konsoll utgang:
Seat up!
Let's go!
Steer left!
Steer right!
Nå gir det vi ser plutselig mening! :) Vi laget et sykkelobjekt. Vi laget to "delobjekter" for sykkel - et styre og et sete. Vi hevet setet for komfort og av gårde: tråkket og styrte etter behov! :) Metodene vi trenger kalles på de aktuelle objektene. Det hele er enkelt og praktisk. I dette eksemplet forbedrer det å skille ut styret og setet innkapslingen (vi skjuler data om sykkeldelene i den aktuelle klassen) og lar oss lage en mer detaljert abstraksjon. La oss nå se på en annen situasjon. Anta at vi vil lage et program som simulerer en sykkelbutikk og reservedeler til sykler. 
-
Et objekt av en indre klasse kan ikke eksistere uten et objekt av en ytre klasse.
Dette er fornuftig: dette er grunnen til at vi laget
Seat
ogHandlebar
indre klasser i programmet vårt — slik at vi ikke ender opp med foreldreløse styre og seter.Denne koden kompilerer ikke:
public static void main(String[] args) { Handlebar handlebar = new Handlebar(); }
En annen viktig funksjon følger av dette:
-
Et objekt av en indre klasse har tilgang til variablene til den ytre klassen.
La oss for eksempel legge til en
int seatPostDiameter
variabel (som representerer diameteren på setepinnen) tilBicycle
klassen vår.Så i den
Seat
indre klassen kan vi lage endisplaySeatProperties()
metode som viser seteegenskapene:public class Bicycle { private String model; private int weight; private int seatPostDiameter; public Bicycle(String model, int weight, int seatPostDiameter) { this.model = model; this.weight = weight; this.seatPostDiameter = seatPostDiameter; } public void start() { System.out.println("Let's go!"); } public class Seat { public void up() { System.out.println("Seat up!"); } public void down() { System.out.println("Seat down!"); } public void displaySeatProperties() { System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter); } } }
Og nå kan vi vise denne informasjonen i programmet vårt:
public class Main { public static void main(String[] args) { Bicycle bicycle = new Bicycle("Peugeot", 120, 40); Bicycle.Seat seat = bicycle.new Seat(); seat.displaySeatProperties(); } }
Konsoll utgang:
Seat properties: seatpost diameter = 40
Merk:den nye variabelen er deklarert med den strengeste tilgangsmodifikatoren (
private
). Og fortsatt har den indre klassen tilgang! -
Et objekt av en indre klasse kan ikke opprettes i en statisk metode for en ytre klasse.
Dette forklares av de spesifikke egenskapene til hvordan indre klasser er organisert. En indre klasse kan ha konstruktører med parametere, eller bare standard konstruktør. Men uansett, når vi lager et objekt av en indre klasse, overføres en referanse til objektet til den ytre klassen usynlig til det opprettede objektet til den indre klassen. Tross alt er tilstedeværelsen av en slik objektreferanse et absolutt krav. Ellers vil vi ikke være i stand til å lage objekter av den indre klassen.
Men hvis en metode for den ytre klassen er statisk, så har vi kanskje ikke et objekt av den ytre klassen! Og dette ville være et brudd på logikken i hvordan en indre klasse fungerer. I denne situasjonen vil kompilatoren generere en feil:
public static Seat createSeat() { // Bicycle.this cannot be referenced from a static context return new Seat(); }
-
En indre klasse kan ikke inneholde statiske variabler og metoder.
Logikken er den samme: statiske metoder og variabler kan eksistere og kalles eller refereres til selv i fravær av et objekt.
Men uten et objekt fra den ytre klassen, vil vi ikke ha tilgang til den indre klassen.
En klar motsetning! Dette er grunnen til at statiske variabler og metoder ikke er tillatt i indre klasser.
Kompilatoren vil generere en feil hvis du prøver å lage dem:
public class Bicycle { private int weight; public class Seat { // An inner class cannot have static declarations public static void displaySeatProperties() { System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter); } } }
-
Når du oppretter et objekt av en indre klasse, er tilgangsmodifikatoren viktig.
En indre klasse kan merkes med standard tilgangsmodifikatorer:
public
,private
,protected
, ogpackage private
.Hvorfor betyr dette noe?
Dette påvirker hvor vi kan lage forekomster av den indre klassen i programmet vårt.
Hvis klassen vår
Seat
er erklært sompublic
, kan vi lageSeat
objekter i en hvilken som helst annen klasse. Det eneste kravet er at et objekt av den ytre klassen også må eksistere.Forresten, vi har allerede gjort dette her:
public class Main { public static void main(String[] args) { Bicycle peugeot = new Bicycle("Peugeot", 120); Bicycle.Handlebar handlebar = peugeot.new Handlebar(); Bicycle.Seat seat = peugeot.new Seat(); seat.up(); peugeot.start(); handlebar.left(); handlebar.right(); } }
Vi fikk lett tilgang til den
Handlebar
indre klassen fraMain
klassen.Hvis vi erklærer den indre klassen som
private
, vil vi kunne lage objekter kun innenfor den ytre klassen.Vi kan ikke lenger lage et
Seat
objekt "på utsiden":private class Seat { // Methods } public class Main { public static void main(String[] args) { Bicycle bicycle = new Bicycle("Peugeot", 120, 40); // Bicycle.Seat has private access in Bicycle Bicycle.Seat seat = bicycle.new Seat(); } }
Du forstår sikkert logikken allerede :)
-
Tilgangsmodifikatorer for indre klasser fungerer på samme måte som for vanlige variabler.
Modifikatoren
protected
gir tilgang til en forekomstvariabel i underklasser og klasser som er i samme pakke.protected
fungerer også for indre klasser. Vi kan lageprotected
objekter av den indre klassen:- i ytre klasse;
- i sine underklasser;
- i klasser som er i samme pakke.
Hvis den indre klassen ikke har en tilgangsmodifikator (
package private
), kan objekter i den indre klassen opprettes:- i ytre klasse;
- i klasser som er i samme pakke.
Du har vært kjent med modifikatorer lenge, så ingen problemer her.
GO TO FULL VERSION