In dieser kurzen Lektion werden einige Tipps zum Arbeiten mit inneren Klassen in Java beschrieben. Diese Lektion ist Teil einer laufenden Reihe von Tutorials für Entwickler, die Java lernen, um Android-Anwendungen zu entwickeln.
In Java können Klassen ineinander geschachtelt werden, um Daten und Funktionalität ordnungsgemäß zu organisieren. Anonyme innere Klassen sind im Grunde eine Abkürzung für Entwickler, sodass der Entwickler ein benutzerdefiniertes Objekt auf einmal erstellen, definieren und verwenden kann. Anonyme innere Klassen werden in Android häufig verwendet, um Handler für Steuerelemente zu definieren, neue Threads zu definieren und zu starten und benutzerdefinierte Objekte in Methoden zu erstellen und zurückzugeben, ohne den Code mit unnötigen Einstellungen zu stören.
Eine ausführliche Besprechung verschachtelter und innerer Klassen, einschließlich anonymer innerer Klassen, finden Sie in unserem Lernprogramm mit dem Titel Learn Java für Android-Entwicklung: Innere Klassen
Manchmal möchten Sie auf Informationen zugreifen, die außerhalb der inneren Klasse verfügbar sind. Betrachten Sie das folgende Beispiel. Sie haben einen Bildschirm mit zwei Steuerelementen: einem Button und einem TextView. Jedes Mal, wenn der Benutzer auf das Button-Steuerelement klickt, wird das TextView-Steuerelement mit der aktuellen Uhrzeit aktualisiert. Innerhalb der mit diesem Layout verknüpften Aktivitätsklasse können Sie könnte Implementieren Sie diese Funktionalität wie folgt:
Button myButton = (Button) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (new View.OnClickListener () public void onClick (View v) SimpleDateFormat formatter = neu SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (new Date ()); TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); myTextview.setText ("Clicked at" + strWhen);;
Der obige Code wird wie erwartet ausgeführt. Angenommen, Sie wollten das TextView-Steuerelement wirklich außerhalb der inneren Klasse deklarieren und auch für andere Zwecke verwenden. Vielleicht würden Sie stattdessen versuchen, dies zu tun:
TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Button myButton = (Button) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (new View.OnClickListener () public void onClick (View v) SimpleDateFormat formatter = neues SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (new Date ()); myTextview. setText ("Clicked at" + strWhen););
Leider wird dies nicht kompiliert. Stattdessen wird der Kompilierungsfehler "Kann sich nicht auf eine nicht endgültige Variable myTextview innerhalb einer inneren Klasse beziehen, die in einer anderen Methode definiert ist" angezeigt. Wie der Fehler vermuten lässt, müssen Sie die TextView-Variable als final definieren, sodass sie innerhalb der onClick () - Methode der inneren Klasse verfügbar ist:
final TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Button myButton = (Button) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (new View.OnClickListener () public void onClick (View v) SimpleDateFormat formatter = neues SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (new Date ()); myTextview. setText ("Clicked at" + strWhen););
Dieser Code wird in der Tat wie erwartet kompiliert und ausgeführt.
Indem Sie die TextView-Variable im vorherigen Beispiel als final definieren, haben Sie sie für die anonyme innere Klasse (oder für jede innere Klasse, die innerhalb ihres Gültigkeitsbereichs definiert ist) verfügbar gemacht. Hier sind einige andere Dinge, die Sie über die endgültigen Variablen wissen sollten:
In Java können Sie das Special verwenden diese referenz, um auf die spezifische Instanz eines Objekts zu verweisen. Was passiert also, wenn Sie eine Klasse mit einer inneren Klasse haben oder eine anonyme innere Klasse? Nun, die innere Klasse kann auf diese spezielle Instanz der umgebenden Klasse zugreifen und hat auch diese eigene Referenz. Um auf diese Instanz für die innere Klasse zuzugreifen, verwenden Sie einfach diese Syntax. Um auf diese Instanz der umschließenden Klasse zuzugreifen, müssen Sie den Namen der umschließenden Klasse anschlagen, dann einen Punkt und dann diesen. Zum Beispiel:
MyEnclosingClass.this
Sehen Sie sich die vollständige Implementierung der anonymen inneren Klasse, wie oben beschrieben, im vollständigen Kontext der umgebenden Klasse an, hier als ClassChaosActivity bezeichnet:
Paket com.androidbook.classchaos; import java.text.SimpleDateFormat; import java.util.Date; import android.app.Activity; import android.os.Bundle; import android.util.Log; Import android.view.View; import android.widget.Button; import android.widget.TextView; public class ClassChaosActivity erweitert die Aktivität public static final String DEBUG_TAG = "MyLoggingTag"; /** Wird aufgerufen, wenn die Aktivität erstellt wird. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); final TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Button myButton = (Button) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (new View.OnClickListener () public void onClick (View v) SimpleDateFormat formatter = neues SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (new Date ()); myTextview. setText ("Clicked at" + strWhen); Log.v (DEBUG_TAG ") Dieser Klassenname:" + this.getClass (). getName ()); Log.v (DEBUG_TAG ") erweitert die folgende Schnittstelle:" + this ". getClass (). getInterfaces () [0] .getName ()); Log.v (DEBUG_TAG, "dieser einschließende Klassenname:" + this.getClass (). getEnclosingClass (). getName ()); Log.v (DEBUG_TAG) , "das ist anonyme Klasse?" + this.getClass (). isAnonymousClass ()); Log.v (DEBUG_TAG, "ClassChaosActivity.this Klassenname"): "+ ClassChaosActivity.this.getClass (). getName ()); log. v (DEBUG_TAG, "ClassChaosActivity.this Super Class Name:" + ClassChaosActivity.this.getClass (). getSuperclass (). getName ()); Log.v (DEBUG_TAG, "ClassChaosActivity.this Ist eine anonyme Klasse?" + KlasseChaosActivity.th .getClass (). isAnonymousClass ()););
Die Protokollausgabe für das Klicken der Schaltfläche läuft wie folgt ab:
10-24 18: 18: 53.075: VERBOSE / MyLoggingTag (751): dieser Klassenname: com.androidbook.classchaos.ClassChaosActivity $ 1 10-24 18: 18: 53.085: VERBOSE / MyLoggingTag (751): Dadurch wird die Schnittstelle mit dem Namen android erweitert .view.View $ OnClickListener 10-24 18: 18: 53.085: VERBOSE / MyLoggingTag (751): this Einschließender Klassenname: com.androidbook.classchaos.ClassChaosActivity 10-24 18: 18: 53.095: VERBOSE / MyLoggingTag (751): Dies ist eine anonyme Klasse. true 10-24 18: 18: 53.095: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Klassenname: com.androidbook.classchaos.ClassChaosActivity 10-24 18: 18: 53.105: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Über Klassenname: android.app.Activity 10-24 18: 18: 53.105: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Ist eine anonyme Klasse? falsch
Wie Sie sehen, bezieht sich dieses Schlüsselwort allein auf die nächstgelegene Klasse, die innere Klasse. Obwohl die innere Klasse anonym ist, gibt Java ihr eine Nummer ClassChaosActivity $ 1, um den Überblick zu behalten. Dies ist zwar für Entwickler an sich nicht nützlich, zeigt jedoch, dass die anonyme innere Klasse wie jede andere Klasse intern behandelt wird. Inzwischen greifen wir auf die umgebende Klasseninstanz mit der ClassChaosActivity.th dieser Syntax zu.
In dieser kurzen Lektion haben Sie verschiedene Tipps gelernt, die Ihnen helfen, innere Klassen und anonyme innere Klassen geschickter zu verwenden. Sie haben gelernt, dass innere Klassen auf Variablen zugreifen können, die außerhalb ihres Gültigkeitsbereichs deklariert sind, vorausgesetzt, die Variablen sind als endgültig und daher nicht änderbar. Sie haben auch die spezielle Syntax für dieses Schlüsselwort "Schlüsselwort" kennengelernt, wenn es um den Zugriff auf innere Klasseninstanzdaten sowie auf die sie umgebenden Klasseninstanzdaten geht.
Die mobilen Entwickler Lauren Darcey und Shane Conder haben mehrere Bücher zur Android-Entwicklung mitgeschrieben: ein ausführliches Programmierbuch mit dem Titel Android Wireless-Anwendungsentwicklung und Sams TeachYourself Entwicklung von Android-Anwendungen in 24 Stunden. Wenn sie nicht schreiben, verbringen sie ihre Zeit damit, mobile Software in ihrem Unternehmen zu entwickeln und Beratungsdienste anzubieten. Sie können sie per E-Mail an [email protected], über ihren Blog unter androidbook.blogspot.com und über Twitter @androidwireless erreichen.