class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
Dessa interna klasser kallas kapslade. De är indelade i 2 typer:
- Icke-statiska kapslade klasser. Dessa kallas också inre klasser.
- Statiska kapslade klasser.
- en lokal klass
- en anonym klass

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!");
}
}
}
Här har vi Bicycle
klassen. Den har 2 fält och 1 metod: start()
. 
Handlebar
och Seat
. Deras kod är skriven i Bicycle
klassen. Dessa är fullfjädrade klasser: som du kan se har var och en av dem sina egna metoder. Vid det här laget kanske du har en fråga: varför i hela friden skulle vi placera en klass i en annan? Varför göra dem till inre klasser? Tja, anta att vi behöver separata klasser för begreppen styre och säte i vårt program. Naturligtvis är det inte nödvändigt för oss att göra dem kapslade! Vi kan göra vanliga klasser. Till exempel, så här:
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!");
}
}
Mycket bra fråga! Naturligtvis är vi inte begränsade av tekniken. Att göra det är definitivt ett alternativ. Här är det viktiga mer den korrekta utformningen av klasserna utifrån ett specifikt program och dess syfte. Inre klasser är till för att separera en entitet som är oupplösligt kopplad till en annan entitet. Styre, säten och pedaler är komponenter i en cykel. Separerade från cykeln gör de inte så mycket mening. Om vi gjort alla dessa begrepp separata offentliga klasser, skulle vi ha haft koden så här i vårt program:
public class Main {
public static void main(String[] args) {
Handlebar handlebar = new Handlebar();
handlebar.right();
}
}
Hmm... Innebörden av den här koden är till och med svår att förklara. Vi har ett vagt styre (Varför är det nödvändigt? Ingen aning om jag ska vara ärlig). Och det här handtaget svänger höger... helt av sig självt, utan cykel... av någon anledning. Genom att skilja konceptet med styret från konceptet med cykeln tappade vi lite logik i vårt program. Med en inre klass ser koden väldigt annorlunda 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();
}
}
Konsolutgång:
Seat up!
Let's go!
Steer left!
Steer right!
Nu är det vi ser plötsligt vettigt! :) Vi skapade ett cykelobjekt. Vi skapade två "delobjekt" för cykel - ett styre och ett säte. Vi höjde sätet för komfort och iväg: trampade och styrde efter behov! :) Metoderna vi behöver anropas på lämpliga objekt. Det hela är enkelt och bekvämt. I det här exemplet förbättrar separeringen av styret och sätet inkapslingen (vi döljer data om cykeldelarna i den relevanta klassen) och låter oss skapa en mer detaljerad abstraktion. Låt oss nu titta på en annan situation. Anta att vi vill skapa ett program som simulerar en cykelaffär och reservdelar till cyklar. 
-
Ett objekt av en inre klass kan inte existera utan ett objekt av en yttre klass.
Detta är vettigt: det är därför vi skapade klasserna
Seat
ochHandlebar
inre klasserna i vårt program - så att vi inte slutar med föräldralösa styre och säten.Denna kod kompilerar inte:
public static void main(String[] args) { Handlebar handlebar = new Handlebar(); }
En annan viktig egenskap följer av detta:
-
Ett objekt i en inre klass har tillgång till variablerna för den yttre klassen.
Låt oss till exempel lägga till en
int seatPostDiameter
variabel (som representerar sadelstolpens diameter) till vårBicycle
klass.Sedan i den
Seat
inre klassen kan vi skapa endisplaySeatProperties()
metod som visar sätesegenskaperna: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); } } }
Och nu kan vi visa denna information i vårt program:
public class Main { public static void main(String[] args) { Bicycle bicycle = new Bicycle("Peugeot", 120, 40); Bicycle.Seat seat = bicycle.new Seat(); seat.displaySeatProperties(); } }
Konsolutgång:
Seat properties: seatpost diameter = 40
Notera:den nya variabeln deklareras med den mest strikta åtkomstmodifieraren (
private
). Och ändå har den inre klassen tillgång! -
Ett objekt av en inre klass kan inte skapas i en statisk metod för en yttre klass.
Detta förklaras av de specifika egenskaperna hos hur inre klasser är organiserade. En inre klass kan ha konstruktorer med parametrar, eller bara standardkonstruktorn. Men oavsett, när vi skapar ett objekt av en inre klass, överförs en referens till objektet för den yttre klassen osynligt till det skapade objektet av den inre klassen. När allt kommer omkring är närvaron av en sådan objektreferens ett absolut krav. Annars kommer vi inte att kunna skapa objekt av den inre klassen.
Men om en metod för den yttre klassen är statisk, så kanske vi inte har ett objekt av den yttre klassen! Och detta skulle vara ett brott mot logiken i hur en inre klass fungerar. I den här situationen kommer kompilatorn att generera ett fel:
public static Seat createSeat() { // Bicycle.this cannot be referenced from a static context return new Seat(); }
-
En inre klass kan inte innehålla statiska variabler och metoder.
Logiken är densamma: statiska metoder och variabler kan existera och anropas eller refereras även i frånvaro av ett objekt.
Men utan ett objekt från den yttre klassen kommer vi inte att ha tillgång till den inre klassen.
En klar motsägelse! Det är därför statiska variabler och metoder inte är tillåtna i inre klasser.
Kompilatorn kommer att generera ett fel om du försöker skapa 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 skapar ett objekt av en inre klass är dess åtkomstmodifierare viktig.
En inre klass kan märkas med standardåtkomstmodifierarna:
public
,private
,protected
, ochpackage private
.Varför spelar detta roll?
Detta påverkar var vi kan skapa instanser av den inre klassen i vårt program.
Om vår
Seat
klass deklareras sompublic
, kan vi skapaSeat
objekt i vilken annan klass som helst. Det enda kravet är att ett objekt av den yttre klassen också måste finnas.Förresten, vi har redan gjort det här:
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 fick lätt tillgång till den
Handlebar
inre klassen frånMain
klassen.Om vi deklarerar den inre klassen som
private
, kommer vi att kunna skapa objekt endast inom den yttre klassen.Vi kan inte längre skapa ett
Seat
objekt "på utsidan":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 förstår säkert redan logiken :)
-
Åtkomstmodifierare för inre klasser fungerar på samma sätt som för vanliga variabler.
Modifieraren
protected
ger tillgång till en instansvariabel i underklasser och klasser som finns i samma paket.protected
fungerar även för inre klasser. Vi kan skapaprotected
objekt av den inre klassen:- i den yttre klassen;
- i dess underklasser;
- i klasser som är i samma paket.
Om den inre klassen inte har en åtkomstmodifierare (
package private
), kan objekt av den inre klassen skapas:- i den yttre klassen;
- i klasser som är i samma paket.
Du har varit bekant med modifierare länge, så inga problem här.
GO TO FULL VERSION