Jede .java-Datei kann maximal eine public Klasse/Interface/… enthalten, aber beliebig viele non-public-EInheiten. Beispiel:

public class A { … }
class B { … }

Statische innere Klassen

  • Im Grunde ganz normale Klassen
  • Um ein Objekt zu erstellen, muss die umschließende Klasse in Punktnotation vorausgestellt werden
  • Die innere Klasse kann auf alle statischen Methoden und Attribute der Äußeren Klasse zugreifen, auch wenn sie private sind
class Aussen {
    static class Innen { }
}
 
// main:
 
Aussen a = new Aussen ();
Aussen.Innen b = new Aussen.Innen();

Anwendungsbeispiel

  • Kann als Comparator verwendet werden, der dann die umschließende Klasse vergleichen kann
class Person {
    // ...
    static class Namensvergleich implements Comparator<Person> {
        @Override public int compare(Person p1, Person p2) {
            return p1.name.compareTo(p2.name);
        }
    }
}
 
// main:
 
Person[] personen = { new Person(...) ... };
Arrays.sort(personen, new Person.Namensvergleich());

Nicht-statische innere Klassen

  • Können nur innerhalb von Instanzen der äußeren Klasse existieren
  • Das innere Objekt hat vollen Zugriff auf alle Attribute und Methoden der äußeren Klasse
class Aussen {
    class Innen { }
}
 
// main:
 
Aussen a = new Aussen();
 
Aussen.Innen i1 = new Aussen().new Innen2();
Aussen.Innen i2 = a.new Innen2();
  • Da es zwei unterschiedliche Objekte gibt, existieren auch zwei verschiedene this und super-Referenzen
  • Bei namensgleichen Attributen muss bei this bzw. super der Klassenname in Punktnotation vorangestellt werden
class Aussen {
    String name = "Aussen";
    
    class Innen {
        String name = "Innen";
 
        String getNames() {
            return Aussen.this.name + ", " + name;
        }
    }
}

Lokale Klassen

  • Klassen, die in Methoden oder sogar in einem beliebigen Block definiert werden
  • Können auf Attribute und Methoden der äußeren Klasse zugreifen
  • Können auf lokale Variablen des umgebenden Blocks zugreifen, diese müssen final oder effectively final sein, ansonsten liegt ein Syntaxfehler vor
public static void main(String[] args) {
 
    int nr = 4711; // effectively final
    
    class LocalClass {
        LocalClass() { 
            System.out.println(nr);
        }
    }
    
    new LocalClass();
    // Ausgabe: 4711
}

Anonyme Klassen

  • Namenslose Klassen
  • Implementieren ein Interface oder erweitern eine (abstrakte) Klasse
class Aussen {
 
    void methode() {
    
        // Innere Klasse
        new Object() {
            // Methoden überschreiben...
        };
    }
}
  • Nützlich für z.B. Comparatoren:
var vergleich = new Comparator<String>() { 
    @Override public int compare(String s1, String s2) {
        return Integer.compare(s1.length(), s2.length());
    }
};
 
Arrays.sort(namen, vergleich);