Innere Klassen in Java – Mit anonymen Klassen Funktionszeiger nachbilden

Eine weitere Form von inneren Klassen in Java sind anonyme Klassen. Diese besitzen, wie der Name schon nahelegt, keinen eigenen Klassennamen.

Eine anonyme Klasse wird in Java in einem kombinierten Schritt definiert und instanziert. Damit dies aber möglich ist, muss entweder:

  • eine andere Klasse bereits vorhanden sein, von der sich die anonyme Klasse ableitet oder
  • ein Interface, das von der anonymen Klasse implementiert wird
plhq_teaser_hbox_gelb_fotolia_RA Studio_46292813

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

Eine große Bedeutung haben anonyme Klassen bei der Programmierung von grafischen Benutzeroberflächen, wo sie für die Definition von Listenern verwendet werden.

In diesem Beitrag stellen wir in den folgenden beiden Abschnitten jeweils eine Java-Beispielanwendung für jede der beiden Verwendungsarten von anonymen Klassen vor.

Mit Hilfe einer anonymen Klasse ein Interface implementieren

In der folgenden Java-Beispielanwendung werden wir zwei anonyme Klassen das Interface CalculatorMethod implementieren lassen. Dazu muss die anonyme Klasse mit dem Namen des Interfaces instanziert werden, welches sie implementieren soll.

Mit Hilfe der anonymen Klasse wird ein Funktionszeiger nachgebildet und mit dessen Hilfe Codeelemente zwischen verschiedenen Programmteilen ausgetauscht. Mehr über das Nachbilden von Funktionszeigern könnt ihr in folgendem Beitrag erfahren: Mit Hilfe von Interfaces Funktionszeiger in Java nachbilden.

Der folgende Java-Quelltext definiert unsere erste Beispielanwendung, in der eine anonyme Klasse das Interface CalculatorMethod implementiert:

Beispielanwendung: die Testklasse für anonyme Klassen

/*
* Beispielanwendung: die Testklasse für eine anonyme Klasse als Funktionszeiger
*/

interface CalculatorMethod
{
  public abstract String getButtonType();

  // wird implizit als public abstract deklariert
  int berechneWert(int a, int b);
}


public class AnonymClassTest
{
  public static void gebeWerteAus(CalculatorMethod cmObjekt, int a, int b)
  {
    int ergebnis = cmObjekt.berechneWert(a, b);
    String buttonType = cmObjekt.getButtonType();

    System.out.println("\nDer " + buttonType + "-Button wurde geklickt.");
    System.out.println(a + " " + buttonType + " " + b + " = " + ergebnis);
  }

  public static void main (String[] args)
  {
    gebeWerteAus(
      new CalculatorMethod()
      {
        public String getButtonType()
        {
          return "PLUS";
        }
  
        public int berechneWert(int a, int b)
        {
          return a + b;
        }
      }
    , 10, 5);

    gebeWerteAus(
      new CalculatorMethod()
      {
        public String getButtonType()
        {
          return "MINUS";
        }
  
        public int berechneWert(int a, int b)
        {
          return a - b;
        }
      }
    , 10, 5);
  }
}

Zuerst definieren wir das Interface CalculatorMethod mit den beiden abstrakten Interface-Methoden getButtonType() und berechneWert(int a, int b). Diese beiden Methoden werden später von unserer anonymen Klasse implementiert.

Anschließend definieren wir die Testklasse AnonymClassTest, die unsere beiden anonymen Klassen enthält. In der main-Methode definieren und instanzieren wir dann unsere beiden anonymen Klassen, die beide das Interface CalculatorMethod implementieren.

In Zeile 28 wird die erste anonyme Klasse definiert und dabei gleichzeitig eine Instanz von ihr erzeugt. Dazu wird der new-Operator zusammen mit dem Namen des Interfaces CalculatorMethod verwendet. Direkt danach folgt die Klassendefinition unserer lokalen anonymen Klasse in geschweiften Klammern.

Unsere anonyme Klasse implementiert die beiden Interface-Methoden getButtonType() und berechneWert(int a, int b). Daher muss bei dem Ausdruck new CalculatorMethod() immer der Name des Interfaces angegeben werden, das von der anonymen Klasse implementiert werden soll.

Bei dem Aufruf in Zeile 27 werden der Methode gebeWerteAus drei Argumente übergeben. Diese sind: eine Instanz unserer lokalen anonymen Klasse, die Zahl 10 und die Zahl 5. Der Aufruf erstreckt sich von Zeile 27 bis 40.

Die Methode gebeWerteAus arbeitet mit der Instanz unserer anonymen Klasse und kann dadurch die Methodenimplementierungen dieser anonymen Klasse aufrufen. Die Instanz unserer anonymen Klasse existiert nur einmal.

Wir können dadurch der Methode gebeWerteAus ganz bestimmten, an die Situation angepassten Programmcode übergeben der vielleicht nur ein einziges Mal in unserem Programm benötigt wird. Genau für solche Zwecke wurden anonyme Klassen in Java eingeführt.

In Zeile 43 wird unsere zweite anonyme Klasse definiert und sogleich instanziert. Sie implementiert auch die beiden Interface-Methoden, diesmal aber mit leicht verändertem Programmcode.

Die Konsolenausgabe der Beispielanwendung ist in der unteren Abbildung dargestellt. Es ist zu erkennen, dass der Java-Compiler bei anonymen inneren Klassen eine fortlaufende Nummer vergibt, da sie über keinen Klassennamen verfügen. Vor die laufende Nummer wird vom Compiler ein $-Zeichen zur Trennung eingefügt.

Java Innere Klasse Anonyme

Mit Hilfe anonymer Klassen, die ein Interface implementiert, Funktionszeiger nachbilden in Java – Ausgabe der Beispielanwendung

Eine anonyme Klasse von einer anderen Klasse ableiten

In der folgenden Java-Beispielanwendung werden wir zwei anonyme Klassen von den Klassen CalculatorMethodClass und CalculatorMethodAbstractClass ableiten. Dazu müssen die anonymen Klassen jeweils mit dem Klassennamen der Vaterklasse (superklasse) instanziert werden, von der sie abgeleitet werden sollen.

Der folgende Java-Quelltext definiert unsere zweite Beispielanwendung, in der zwei anonyme Klassen verwendet werden:

Beispielanwendung: die Testklasse für anonyme Klassen

/*
* Beispielanwendung: die Testklasse für eine anonyme Klasse als Funktionszeiger,
*                    welche sich von einer anderen Klasse ableitet
*/

abstract class CalculatorMethodAbstractClass
{
  public abstract String getButtonType();
  public abstract int berechneWert(int a, int b);
}

class CalculatorMethodClass
{
  public String getButtonType() { return "";}
  public int berechneWert(int a, int b) { return 0;}
}


public class AnonymClassTest
{
  public static void gebeWerteAus(CalculatorMethodClass cmObjekt, int a, int b)
  {
    int ergebnis = cmObjekt.berechneWert(a, b);
    String buttonType = cmObjekt.getButtonType();

    System.out.println("\nDer " + buttonType + "-Button wurde geklickt.");
    System.out.println(a + " " + buttonType + " " + b + " = " + ergebnis);
  }

  public static void gebeWerteAus2(CalculatorMethodAbstractClass cmObjekt, int a, int b)
  {
    int ergebnis = cmObjekt.berechneWert(a, b);
    String buttonType = cmObjekt.getButtonType();

    System.out.println("\nDer " + buttonType + "-Button wurde geklickt.");
    System.out.println(a + " " + buttonType + " " + b + " = " + ergebnis);
  }

  public static void main (String[] args)
  {
    gebeWerteAus(
      new CalculatorMethodClass()
      {
        public String getButtonType()
        {
          return "PLUS";
        }
  
        public int berechneWert(int a, int b)
        {
          return a + b;
        }
      }
    , 10, 5);

    gebeWerteAus2(
      new CalculatorMethodAbstractClass()
      {
        public String getButtonType()
        {
          return "MINUS";
        }
  
        public int berechneWert(int a, int b)
        {
          return a - b;
        }
      }
    , 10, 5);
  }
}

Zuerst werden die beiden Klassen CalculatorMethodAbstractClass und CalculatorMethodClass definiert. Beide Klassen enthalten die Methoden getButtonType() und berechneWert(int a, int b), wobei diese beiden Methoden in der abstrakten Klasse CalculatorMethodAbstractClass nicht konkret sind und somit auch noch nicht ausprogrammiert, sondern abstrakt.

Anschließend werden in der Testklasse AnonymClassTest die Methoden gebeWertAus, gebeWertAus2 und main definiert. In der main-Methode werden die beiden anonymen Klassen definiert und sogleich instanziert.

In Zeile 42 wird die erste anonyme Klasse definiert und instanziert, dabei wird eine Instanz der anonymen Klasse erzeugt. Durch den Ausdruck new CalculatorMethodClass() wird eine anonyme Klasse definiert und von der Vaterklasse CalculatorMethodClass abgeleitet. Die Instanz der anonymen Klasse vom Typ CalculatorMethodClass wird als erstes Argument der Methode gebeWertAus übergeben.

Der Methodenaufruf erstreckt sich von Zeile 41 bis 54. Als weitere Argumente werden der Methode gebeWertAus neben der Instanz der anonymen Klasse noch die Integer Zahl 10 und 5 übergeben.

Android Apps Programmieren Online-Kurs

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

Die Methodenimplementierungen der anonymen Klasse überlagern dabei die beiden Methoden ihrer Vaterklasse, so dass die Methode gebeWertAus mit den Methodenversionen der anonymen Klasse arbeiten kann.

In Zeile 57 wird die zweite anonyme Klasse definiert und sofort an dieser Stelle auch instanziert. Diesmal wird durch den Ausdruck new CalculatorMethodAbstractClass() die anonyme Klasse von der abstrakten Klasse CalculatorMethodAbstractClass abgeleitet. Der Methodenaufruf verläuft von Zeile 56 bis 69.

Die zweite anonyme Klasse implementiert die beiden abstrakten Methoden ihrer abstrakten Vaterklasse. Die Instanz der anonymen Klasse vom Typ CalculatorMethodAbstractClass wird an die Methode gebeWertAus2 übergeben, dadurch kann die Methode mit den Methodenversionen der anonymen Klasse arbeiten.

Wie im vorherigen Beispiel, wird auch diesmal mit Hilfe von anonymen Klassen gezielt Programmcode an eine andere Programmstelle übermittelt. Im Moment mag dies noch etwas umständlich erscheinen, später, bei der Programmierung von grafischen Benutzeroberflächen, wird der große Nutzen von anonymen Klassen klar erkennbar werden.


Die Konsolenausgabe der Beispielanwendung ist in der unteren Abbildung dargestellt. Es ist zu erkennen, dass der Java-Compiler bei anonymen inneren Klassen eine fortlaufende Nummer vergibt, da sie über keinen Klassennamen verfügen. Vor die laufende Nummer wird vom Compiler ein $-Zeichen zur Trennung eingefügt.

Java Innere Klasse Anonyme

Mit Hilfe einer anonymen Klasse, die sich von einer anderen Klasse ableitet, Funktionszeiger nachbilden in Java – Ausgabe der Beispielanwendung

Mit dem folgenden Link geht es zurück zu dem Programmieren Lernen HQ Java Kurs.


Comments 1

  1. Pingback: Klassen in Java: Die Grundlagen der objektorientierten Programmierung

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.