class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
Diese internen Klassen werden als verschachtelt bezeichnet. Sie sind in 2 Typen unterteilt:
- Nicht statische verschachtelte Klassen. Diese werden auch innere Klassen genannt.
- Statisch verschachtelte Klassen.
- eine lokale Klasse
- eine anonyme 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!");
}
}
}
Hier haben wir die Bicycle
Klasse. Es hat 2 Felder und 1 Methode: start()
. 
Handlebar
und Seat
. Ihr Code wird innerhalb der Bicycle
Klasse geschrieben. Dabei handelt es sich um vollwertige Klassen: Wie Sie sehen, hat jede von ihnen ihre eigenen Methoden. An diesem Punkt haben Sie vielleicht eine Frage: Warum in aller Welt sollten wir eine Klasse in eine andere einordnen? Warum sie zu inneren Klassen machen? Angenommen, wir benötigen in unserem Programm separate Klassen für die Konzepte Lenker und Sitz. Natürlich ist es für uns nicht notwendig, sie zu verschachteln! Wir können normale Kurse machen. Zum Beispiel so:
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!");
}
}
Sehr gute Frage! Natürlich sind wir nicht durch die Technologie eingeschränkt. Das ist sicherlich eine Option. Hier kommt es vielmehr auf die richtige Gestaltung der Kurse im Hinblick auf ein bestimmtes Programm und dessen Zweck an. Innere Klassen dienen dazu, eine Entität abzutrennen, die untrennbar mit einer anderen Entität verbunden ist. Lenker, Sitze und Pedale sind Bestandteile eines Fahrrads. Getrennt vom Fahrrad machen sie wenig Sinn. Wenn wir alle diese Konzepte zu separaten öffentlichen Klassen gemacht hätten, hätten wir den folgenden Code in unserem Programm gehabt:
public class Main {
public static void main(String[] args) {
Handlebar handlebar = new Handlebar();
handlebar.right();
}
}
Hmm ... Die Bedeutung dieses Codes ist sogar schwer zu erklären. Wir haben einen vagen Lenker (Warum ist er notwendig? Keine Ahnung, um ehrlich zu sein). Und dieser Griff dreht sich nach rechts... ganz von alleine, ohne Fahrrad... aus irgendeinem Grund. Durch die Trennung des Konzepts des Lenkers vom Konzept des Fahrrads haben wir in unserem Programm etwas an Logik verloren. Bei Verwendung einer inneren Klasse sieht der Code ganz anders aus:
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();
}
}
Konsolenausgabe:
Seat up!
Let's go!
Steer left!
Steer right!
Jetzt macht das, was wir sehen, plötzlich Sinn! :) Wir haben ein Fahrradobjekt erstellt. Wir haben zwei Fahrrad-„Unterobjekte“ erstellt – einen Lenker und einen Sitz. Wir stellten den Sitz hoch, um es bequemer zu machen, und los ging es: Treten und lenken Sie nach Bedarf! :) Die von uns benötigten Methoden werden für die entsprechenden Objekte aufgerufen. Es ist alles einfach und bequem. In diesem Beispiel verbessert die Trennung von Lenker und Sitz die Kapselung (wir verbergen Daten zu den Fahrradteilen innerhalb der relevanten Klasse) und ermöglicht uns die Erstellung einer detaillierteren Abstraktion. Schauen wir uns nun eine andere Situation an. Angenommen, wir möchten ein Programm erstellen, das einen Fahrradladen und Ersatzteile für Fahrräder simuliert. 
-
Ein Objekt einer inneren Klasse kann nicht ohne ein Objekt einer äußeren Klasse existieren.
Das macht Sinn: Aus diesem Grund haben wir die
Seat
undHandlebar
inneren Klassen in unser Programm aufgenommen – damit wir nicht mit verwaisten Lenkern und Sitzen enden.Dieser Code lässt sich nicht kompilieren:
public static void main(String[] args) { Handlebar handlebar = new Handlebar(); }
Daraus ergibt sich ein weiteres wichtiges Merkmal:
-
Ein Objekt einer inneren Klasse hat Zugriff auf die Variablen der äußeren Klasse.
Fügen wir unserer Klasse beispielsweise eine
int seatPostDiameter
Variable hinzu (die den Durchmesser der Sattelstütze darstellt)Bicycle
.Dann
Seat
können wir in der inneren Klasse eine Methode erstellen,displaySeatProperties()
die die Sitzeigenschaften anzeigt: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); } } }
Und jetzt können wir diese Informationen in unserem Programm anzeigen:
public class Main { public static void main(String[] args) { Bicycle bicycle = new Bicycle("Peugeot", 120, 40); Bicycle.Seat seat = bicycle.new Seat(); seat.displaySeatProperties(); } }
Konsolenausgabe:
Seat properties: seatpost diameter = 40
Notiz:Die neue Variable wird mit dem strengsten Zugriffsmodifikator (
private
) deklariert. Und trotzdem hat die innere Klasse Zugriff! -
Ein Objekt einer inneren Klasse kann nicht in einer statischen Methode einer äußeren Klasse erstellt werden.
Dies erklärt sich aus den Besonderheiten der Organisation innerer Klassen. Eine innere Klasse kann Konstruktoren mit Parametern oder nur den Standardkonstruktor haben. Unabhängig davon wird jedoch beim Erstellen eines Objekts einer inneren Klasse unsichtbar ein Verweis auf das Objekt der äußeren Klasse an das erstellte Objekt der inneren Klasse übergeben. Schließlich ist das Vorhandensein einer solchen Objektreferenz zwingend erforderlich. Andernfalls können wir keine Objekte der inneren Klasse erstellen.
Aber wenn eine Methode der äußeren Klasse statisch ist, dann haben wir möglicherweise kein Objekt der äußeren Klasse! Und dies wäre ein Verstoß gegen die Logik, wie eine innere Klasse funktioniert. In dieser Situation generiert der Compiler einen Fehler:
public static Seat createSeat() { // Bicycle.this cannot be referenced from a static context return new Seat(); }
-
Eine innere Klasse kann keine statischen Variablen und Methoden enthalten.
Die Logik ist dieselbe: Statische Methoden und Variablen können auch dann existieren und aufgerufen oder referenziert werden, wenn kein Objekt vorhanden ist.
Aber ohne ein Objekt der äußeren Klasse haben wir keinen Zugriff auf die innere Klasse.
Ein klarer Widerspruch! Aus diesem Grund sind statische Variablen und Methoden in inneren Klassen nicht zulässig.
Der Compiler generiert einen Fehler, wenn Sie versuchen, sie zu erstellen:
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); } } }
-
Beim Erstellen eines Objekts einer inneren Klasse ist sein Zugriffsmodifikator wichtig.
Eine innere Klasse kann mit den Standardzugriffsmodifikatoren ,
public
,private
undprotected
markiert werdenpackage private
.Warum ist das wichtig?
Dies wirkt sich darauf aus, wo wir in unserem Programm Instanzen der inneren Klasse erstellen können.
Wenn unsere
Seat
Klasse als deklariert istpublic
, können wirSeat
Objekte in jeder anderen Klasse erstellen. Die einzige Voraussetzung ist, dass auch ein Objekt der äußeren Klasse vorhanden sein muss.Das haben wir hier übrigens schon gemacht:
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(); } }
Von der Klasse aus haben wir leicht Zugang zur
Handlebar
inneren Klasse erhaltenMain
.Wenn wir die innere Klasse als deklarieren
private
, können wir Objekte nur innerhalb der äußeren Klasse erstellen.Wir können kein
Seat
Objekt mehr „außen“ erstellen: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 verstehst die Logik wahrscheinlich schon :)
-
Zugriffsmodifikatoren für innere Klassen funktionieren genauso wie für gewöhnliche Variablen.
Der
protected
Modifikator ermöglicht den Zugriff auf eine Instanzvariable in Unterklassen und Klassen, die sich im selben Paket befinden.protected
Funktioniert auch für innere Klassen.protected
Wir können Objekte der inneren Klasse erstellen :- in der äußeren Klasse;
- in seinen Unterklassen;
- in Klassen, die sich im selben Paket befinden.
Wenn die innere Klasse keinen Zugriffsmodifikator (
package private
) hat, können Objekte der inneren Klasse erstellt werden:- in der äußeren Klasse;
- in Klassen, die sich im selben Paket befinden.
Mit Modifikatoren sind Sie schon lange vertraut, daher gibt es hier keine Probleme.
GO TO FULL VERSION