Lernen Sie Java für die Android-Entwicklung Innere Klassen

In diesem Lernprogramm werden Sie mit dem Konzept der inneren Klassen in Java vertraut gemacht. Hierbei handelt es sich um Klassen, deren Gültigkeitsbereich und Definition sich in einer anderen Klasse befinden. Außerdem lernen Sie anonyme innere Klassen kennen, die bei der Entwicklung mit dem Android SDK häufig verwendet werden.

Android-Anwendungen werden in Java geschrieben, einer objektorientierten Programmiersprache. In diesem Lernprogramm erfahren Sie mehr über innere Klassen, wann und warum sie verwendet werden und wie sie funktionieren. Außerdem lernen Sie, wie Sie mithilfe von anonymen inneren Klassen neue Objekte dynamisch erstellen.

Was du brauchen wirst

Technisch benötigen Sie keine Tools, um dieses Tutorial abzuschließen, aber Sie werden sie sicherlich benötigen, um Android-Anwendungen zu entwickeln.

Um Android-Anwendungen (oder auch beliebige Java-Anwendungen) zu entwickeln, benötigen Sie eine Entwicklungsumgebung zum Schreiben und Erstellen von Anwendungen. Eclipse ist eine sehr beliebte Entwicklungsumgebung (IDE) für Java und die bevorzugte IDE für Android-Entwicklung. Es ist für Windows-, Mac- und Linux-Betriebssysteme kostenlos verfügbar.

Vollständige Anweisungen zur Installation von Eclipse (einschließlich der unterstützten Versionen) und des Android SDK finden Sie auf der Android-Entwicklerwebsite.

Was ist eine innere Klasse??

Die meisten Klassen in Java sind Klassen der obersten Ebene. Diese Klassen und die von ihnen definierten Objekte sind eigenständig. Sie können auch verschachtelte Klassen erstellen, um untergeordnete Objekte, die nur im Kontext der äußeren Klasse von Bedeutung sind, eindeutig zu kapseln und zu definieren. Verschachtelte Klassen werden als innere Klassen bezeichnet.

Innere Klassen können alle Funktionen einer regulären Klasse haben, ihr Umfang ist jedoch begrenzt. Innere Klassen haben einen weiteren Vorteil: Sie haben vollen Zugriff auf die Klasse, in der sie verschachtelt sind. Diese Funktion macht innere Klassen ideal für die Implementierung von Adapterfunktionen wie Iteratoren.

Hier ist ein Beispiel für eine Top-Level-Klasse mit zwei inneren Klassen:

 Öffentliche Klasse Benutzer // Benutzerfelder, einschließlich Variablen des Typs LoginInfo und UserPreferences // Verschiedene Benutzermethoden Klasse LoginInfo // Felder für Anmeldeinformationen // Login / Logout-Methoden // Zugriff auf Benutzerfelder / -methoden Klasse Preferences // Benutzer Einstellungsfelder // Einstellungsmethoden abrufen / festlegen // Einstellungsmethoden zurücksetzen // Kann auf Benutzerfelder / -methoden zugreifen 

In diesem Beispiel hat die User-Klasse zwei innere Klassen: LoginInfo und Preferences. Während alle benutzerbezogenen Daten und Funktionen in der Klasse User definiert werden können, kann die Verwendung der inneren Klassen zur Unterteilung der Funktionalität dazu führen, dass Code einfacher zu lesen und zu verwalten ist. Die inneren Klassen LoginInfo und Preferences haben auch Zugriff auf die geschützten / privaten Felder und Methoden, die in der User-Klasse verfügbar sind. Andernfalls verfügen sie möglicherweise aus Sicherheitsgründen nicht, wenn sie selbst als eigenständige Klassen definiert wurden.

Es ist jedoch wichtig zu wissen, dass innere Klassen nur existieren, um den Entwickler beim Organisieren von Code zu unterstützen. Der Compiler behandelt innere Klassen wie jede andere Klasse, mit der Ausnahme, dass die inneren Klassen einen begrenzten Gültigkeitsbereich haben und daher an die Klasse gebunden sind, mit der sie definiert sind. Anders ausgedrückt, Sie könnten die LoginInfo- oder Preferences-Klassen nur mit einer Instanz der User-Klasse verwenden oder instanziieren, aber die inneren Klassen könnten bei Bedarf auf alle Felder oder Methoden in der äußeren Klasse User zugreifen.

Verwenden von statischen verschachtelten Klassen

Eine besonders nützliche Anwendung für verschachtelte Klassen sind statische verschachtelte Klassen. Eine statische innere Klasse definiert ein Verhalten, das nicht an eine bestimmte Objektinstanz gebunden ist, sondern für alle Instanzen gilt. Zum Beispiel könnten wir der Benutzerklasse eine dritte geschachtelte Klasse hinzufügen, dieses Mal statisch, um die serverbezogene Funktionalität zu steuern:

 Öffentliche Klasse Benutzer // Benutzerfelder, einschließlich Variablen des Typs LoginInfo und UserPreferences // Verschiedene Benutzermethoden Klasse LoginInfo  Öffentliche statische Klasse ServerInfo  // Server-Informationen gelten für alle Instanzen von Benutzer 

Da es sich um eine öffentliche Klasse handelt, kann diese statische verschachtelte Klasse mit der folgenden neuen Anweisung instanziiert werden:

 User.ServerInfo sInfo = new User.ServerInfo (); 

Die äußere Klasse muss nicht instanziiert werden, um diese Instantiierung durchzuführen, also die Verwendung des Klassennamens. Daher hat eine statische verschachtelte Klasse im Gegensatz zu einer nicht statischen verschachtelten Klasse (auch als innere Klasse bezeichnet) keinen Zugriff auf Mitglieder der äußeren Klasse - sie werden möglicherweise nicht einmal instanziiert.

Die Kraft anonymer innerer Klassen

Android verwendet anonyme innere Klassen mit großer Wirkung. Anonyme innere Klassen sind im Wesentlichen eine Abkürzung für Entwickler. Sie ermöglichen es dem Entwickler, ein benutzerdefiniertes Objekt in einer „Zeile“ zu erstellen, zu definieren und zu verwenden. Möglicherweise haben Sie Beispiele für die Verwendung anonymer innerer Klassen im Beispielcode gesehen und nicht realisiert.
Um eine anonyme innere Klasse zu erstellen, geben Sie nur die rechte Seite der Definition an. Beginnen Sie mit dem neuen Schlüsselwort, gefolgt von der Klasse oder dem Interface, die Sie erweitern oder implementieren möchten, gefolgt von der Klassendefinition. Dadurch wird die Klasse erstellt und als Wert zurückgegeben, den Sie dann zum Aufrufen einer Methode verwenden können.
Wenn wir eine anonyme innere Klasse verwenden, wird dem erstellten Objekt kein Name zugewiesen (daher der Begriff anonym). Der Nebeneffekt ist natürlich, dass das Objekt nur einmal verwendet wird. Es ist zum Beispiel üblich, eine anonyme innere Klasse zu verwenden, um eine benutzerdefinierte Version eines Objekts als Rückgabewert zu erstellen. Zum Beispiel erweitern wir hier die Truck-Klasse (vorausgesetzt, sie wird an anderer Stelle definiert und hat ein Feld namens mpg und die beiden Methoden start () und stop ()):

 Truck getTruck () return new Truck () int mpg = 3; void start () / * start der Implementierung * / void stop () / * stop der Implementierung * /;  

Sehen wir uns nun praktische Beispiele für anonyme innere Klassen an, die in Android verwendet werden.

Verwenden einer anonymen inneren Klasse zum Definieren eines Listeners

Android-Entwickler verwenden häufig anonyme innere Klassen, um spezialisierte Listener zu definieren, die Rückrufe für ein bestimmtes Verhalten beim Auftreten eines Ereignisses registrieren. Um beispielsweise Klicks auf ein View-Steuerelement zu überwachen, muss der Entwickler die Methode setOnClickListener () aufrufen, die einen einzelnen Parameter benötigt: ein View.OnClickListener-Objekt.
Entwickler verwenden routinemäßig die anonyme Methode der inneren Klasse, um ihren benutzerdefinierten View.OnClickListener wie folgt zu erstellen, zu definieren und zu verwenden:

 Schaltfläche aButton = (Schaltfläche) findViewById (R.id.MyButton); aButton.setOnClickListener (neuer View.OnClickListener () public void onClick (View v) // Der Benutzer hat auf meine Schaltfläche geklickt, etwas hier tun!); 

Verwenden einer anonymen inneren Klasse zum Starten eines Threads

Schauen wir uns ein anderes Beispiel an. Es ist üblich, eine neue Thread-Klasse zu definieren, die Implementierung der run () -Methode bereitzustellen und diesen Thread auf einmal zu starten:

 new Thread () public void run () doWorkHere ();  .Start(); 

Benannte innere Klasse verwenden

Die Verwendung anonymer innerer Klassen für Zuhörer in Android ist so üblich, dass es praktisch selbstverständlich ist, dies zu tun. Warum möchten Sie sie dann nicht verwenden? Beantworten wir dies durch ein hypothetisches Beispiel.
Nehmen wir an, Sie haben einen Bildschirm mit 100 Schaltflächen (wir haben hypothetisch gesagt, oder?). Lassen Sie uns nun sagen, dass jede Taste das tut, wenn sie gedrückt wird genau das gleiche. In diesem Fall werden wir nur auf Klicks achten und den Text aus dem übergebenen View-Objekt (der auf der angeklickten Schaltfläche angezeigte Text) anstoßen:
Hier ist ein Pseudo-Code, um das zu tun:

 Schaltfläche [] buttons = getAllOneHundredButtonsAsArray (); for (Button button: buttons) button.setOnClickListener (new View.OnClickListener () public void onClick (Ansicht v) showToast (v.getText ());;  

Kurz und elegant, was ist daran falsch? Bei jeder Iteration wird ein neues OnClickListener-Objekt instanziiert. Da jedes genau gleich ist, gibt es keinen guten Grund, 100 davon zu erstellen. Stattdessen können Sie eine einzelne benannte innere Klasse erstellen, diese einmal instanziieren und dann an die setOnClickListener () -Methode übergeben. Zum Beispiel:

 Klasse MyActivity erweitert die Aktivität public void myMethod () MyClickHandler-Handler = new MyClickHandler (); Schaltfläche [] buttons = getAllOneHundredButtonsAsArray (); for (Button button: buttons) button.setOnClickListener (Handler);  Klasse MyClickHandler implementiert View.OnClickListener public void onClick (View v) showToast ((Button) v) .getText ());  

Wenn Sie die Anonymität bevorzugen, können Sie einer Variablen immer noch eine anonyme innere Klasse zuweisen und diese wie folgt verwenden:

 Klasse MyActivity erweitert die Aktivität public void myMethod () View.OnClickListener-Handler = new View.OnClickListener () public void onClick (View v) showToast ((Button) v) .getText ()); ; Schaltfläche [] buttons = getAllOneHundredButtonsAsArray (); for (Button button: buttons) button.setOnClickListener (Handler);  

Die Methode liegt bei Ihnen, bedenken Sie jedoch die möglichen Speicher- und Leistungsprobleme, die beim Instanziieren einer Reihe von Objekten auftreten können.

Ein Hinweis zu Nuancen

Dieses Tutorial ist eine Einführung in innere Klassen in Java. Es gibt Stilüberlegungen und Nuancen, wenn innere Klassen auf unterschiedliche und kreative Weise verwendet werden. Darüber hinaus können Sie weitere Informationen zu den internen Effekten und den Grenzleistungsunterschieden erhalten, die sich zeigen können, wenn Sie verschachtelte Klassen auf unterschiedliche Weise verwenden. All dies geht jedoch weit über den Rahmen dieses Tutorials hinaus.

Ein kurzer Hinweis zur Terminologie

Obwohl wir versucht haben, mit der Terminologie für verschachtelte und innere Klassen konsistent zu sein, ist die Terminologie aus verschiedenen Online- und Offline-Ressourcen nicht immer konsistent. Im Folgenden finden Sie eine Liste von Begriffen aus der aktuellen Sun / Oracle-Dokumentation, die für die Autorisierung auf Java so gut wie alle anderen ist:

  • Geschachtelte Klasse: eine Klasse, die in einer anderen Klasse definiert ist
  • Statische verschachtelte Klasse: eine statische Klasse, die in einer anderen Klasse definiert ist
  • Innere Klasse: eine nicht statische verschachtelte Klasse, die in einer anderen Klasse definiert ist
  • Lokale innere Klasse: eine innerhalb einer Methode definierte Klasse
  • Anonyme innere Klasse: eine unbenannte Klasse, die in einer Methode definiert ist

Verwirrt? Sie können die java.lang.Class-Methoden namens isLocalClass () und isAnonymous () für instanziierte Klassen verwenden, um einige dieser Eigenschaften zu bestimmen. Ein Oracle-Blogeintrag versucht, die Situation auch mit einem schönen Venn-Diagramm ein wenig aufzuklären.

Einpacken

Die Java-Programmiersprache unterstützt verschachtelte Klassen und ermöglicht dem Entwickler eine große Flexibilität bei der Definition von Objekten. Innere Klassen können verwendet werden, um die Klassenfunktionalität zu organisieren oder spezielle Verhaltensweisen zu definieren, die andernfalls erfordern, dass der Entwickler Klassendaten und Funktionen verfügbar macht, die nicht wirklich verfügbar gemacht werden sollten. Statische innere Klassen können verwendet werden, um Felder und Funktionen zu definieren, die für alle Instanzen einer Klasse gelten. Schließlich bieten anonyme innere Klassen eine nützliche Abkürzung für Entwickler, die ein benutzerdefiniertes Objekt auf einmal erstellen, definieren und verwenden möchten.