04.10 Innere Klassen

Lokale Klassen

Eine lokale Klasse (local class) wird – anders als bis jetzt kennengelernt – nicht im Rumpf einer Klasse definiert, sondern direkt in einem Anweisungsblock (Konstruktor, Methode, …). Die Sichtbarkeit der lokalen Klasse darf nicht verändert werden, und sie darf keine statischen Attribute oder Methoden enthalten, die nicht als final deklariert wurden. Zugreifen können solche Klassen auf die Attribute und Methoden der äußeren Klasse, sowie auf die lokalen Variablen und Übergabeparameter, die als final gekennzeichnet wurden. Sollte eine lokale Klasse allerdings in einem statischen Anweisungsblock definiert worden sein, so ist ein Zugriff auf die Objektattribute bzw. Objektmethoden der äußeren Klasse selbstverständlich nicht möglich.

package de.inner;
public class LocalTest {
	
  private static int z = 0;
	
  public static void main(String[] args) {
		
    final int y = 3;
		
    class Local {
    	
      private int i = 1;
      private int z = 4;
			
      Local() {
        this.i = LocalTest.z;
      }
			
      private void printI() {
        System.out.println("I = " + this.i);
      }
			
      private void printY() {
        System.out.println("Y = " + y);
      }
			
      private void printZ() {
        System.out.println("Z = " + this.z);
      }
    }
    Local loc = new Local();
    loc.printI();
    loc.printY();
    loc.printZ();
  }
}

Anonyme, innere Klassen

Diese Klassen (anonymous classes) sind im Prinzip keine eigene Klassen, sondern Klassen, die von anderen Klassen erben und selbige manipulieren/erweitern. Somit können z. B. Instanzen von abstrakten Klassen oder Interfaces erstellt werden, ohne extra eine Klasse zu programmieren, die von dieser Klasse erbt/dieses Interface implementiert. Als Beispiel dient diesmal das Interface CharSequence, welches Sie diverse Methoden zum Auslesen von Zeichenketten implementieren lässt.

package de.inner;
public class Anonym {

  public static void main(String[] args) {
		
    final String aValue = "Java Blog Buch";
		
    CharSequence seq = new CharSequence() {

      private String content = null;

      // Exemplarinitialisierer anstelle
      // eines Konstruktors
      {
        this.content = aValue;
      }
			
      public char charAt(int index) {
        return this.content.charAt(index);
      }

      public int length() {
        return this.content.length();
      }

      public CharSequence subSequence(int start, int end) {
        return this.content.subSequence(start, end);
      }
			
      public String toString() {
        return this.content;
      }
    };
    System.out.println(seq);
  }
}

Eine anonyme, innere Klasse kann keine weiteren Interfaces implementieren, oder von anderen Klassen erben. Auch ist es nicht möglich einen eigenen Konstruktor zu definieren. Als Ersatz können Sie in diesen Klassen Exemplarinitialisierer (Instanz Initialisierer) verwenden (s. o. und das Kapitel über statische Initialisierer). Was statische Attribute und Methoden angeht, bestehen die selben Einschränkungen wie bei lokalen Klassen.

Beliebte Einsatzorte für anonyme, innere Klassen sind Threads und Listener (siehe entsprechende Kapitel).

Implementierung von Interfaces und Vererbung

Ausgenommen der anonymen, inneren Klasse, können alle anderen inneren Klassen auch von anderen Klassen erben oder Interfaces implementieren. Dabei gehen Sie exakt so wie bei normalen Klassen vor.

public class AClass {
  public class InnerClass extends AnOtherClass implements AnInterface {
    ...
  }
}

Übersetzung des Compilers

Der Compiler erzeugt automatisch für jede innere Klasse eine neue .class-Datei. Dabei wird eine bestimmte Formatierung verwendet. Statische, verschachtelte Klassen und innere Klassen werden in der Form „AeussereKlasse$InnereKlasse“ gespeichert (z. B. InnerTest$Inner.class). Lokale Klassen erhalten das Format „AeussereKlasse$FortlaufendeNummer$LokaleKlasse“ (z. B. LokaleKlasse$1$Local.class). Innere, anonyme Klassen werden hingegen nur durch „AeussereKlasse$FortlaufendeNummer“ definiert (z. B. Anonym$1.class).

Import

Um innere Klassen oder statische, verschachtelte Klassen in anderen Klassen zu verwenden, können Sie sie auf drei unterschiedliche Arten ansprechen.

pfad.zur.klasse.AeussereKlasse.InnereKlasse.doSomething();
import package.zur.klasse.AeussereKlasse;
...
  {
    AeussereKlasse.InnereKlasse.doSomething();
  }
import package.zur.klasse.AeussereKlasse.InnereKlasse;
...
  {
    InnereKlasse.doSomething();
  }
Previous Article
Next Article

4 Replies to “04.10 Innere Klassen”

  1. N/A

    Begriffsverwirrung!
    Inner Classes sind niemals static. Statische Nested Classes sind Member-Classes.
    Siehe JLS Kapitel 8

  2. Stefan Kiesel

    Hallo,

    danke für den Hinweis! Da ist wohl versehentlich eine veraltete Version des Kapitels veröffentlicht worden. Ursprünglich waren die Begrifflichkeiten so gewählt, dass sich „irgendwie“ alles auf den Titel des Kapitels (INNERE Klassen) bezieht. Davon bin ich aber mittlerweile abgewichen. Ich werde das umgehend ausbessern.

    Gruß

  3. Gast

    Hallo Stefan,

    geht es bei der Äußerung:

    „Inner Classes sind niemals static. Statische Nested Classes sind Member-Classes.“

    lediglich um die korrekte Begrifflichkeit ?

    Ich habe soeben das folgende Beispiel geschrieben:

    ————————-

    public class KlasseAussen {
    	public static int v1 = 42;	
    	public KlasseAussen() {		
    		InnerClass inner = new InnerClass();
    		System.out.println(inner.v2); // Zugriff nur per Referenz !
    	}	
    	// Innere statische Klasse !   <------------- Falsche Bezeichnung ?! 
    	public static class InnerClass {		
    		public static int v2 = 24;		
    		public InnerClass() {
    			System.out.println(v1);
    		}
    	}	
    	public static void main(String[] args) {
    		KlasseAussen inner = new KlasseAussen();
    	}	
    }

    ————————-

    Ich würde die innere Klasse mit der Bezeichnung ‚InnerClass‘ als statische innere Klasse bezeichnen.

    Sofern ich die Äußerung richtig verstanden haben sollte, wird das was ich als ’statische innere Klasse ‚ bezeichne, als ‚Member-Class oder Nested Classes‘ bezeichnet.
    Die Bezeichnung ’statische innere Klasse ‚ wäre falsch und es gäbe nur eine ’nicht statische innere Klasse‘.

    Korrekt ?

  4. Stefan Kiesel

    Hallo Gast,

    ja, dabei geht es lediglich um die korrekten Begrifflichkeiten, die im Kapitel aber bereits korrigiert wurden.

    Ihre statische, innere Klasse wird als „nested, static class“ oder zu deutsch „geschachtelte, statische Klasse“ bezeichnet. Wenn Sie aber zu jemanden „statische, innere Klasse“ sagen, wird dieser Sie auch ohne Probleme verstehen.

    Eine innere Klasse ist eine Klasse in einer anderen Klasse ohne das Schlüsselwort static. Im Vergleich zu Objektattributen und Klasssenattribute könnte man eine Innere Klasse als Objektklasse und eine static, nested Klasse als Klassenklasse bezeichnen.

    Ich hoffe Ihnen ist nun alles soweit klar. Falls nicht, einfach nachfragen 🙂 .

    Gruß
    Stefan

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.