Referenzen #
Variablen können primitive Datentypen enthalten. Das sind z.B. die Typen int
, double
oder boolean
, die entsprechenden Werte werden direkt in der Variable gespeichert. Bei der Deklaration als Instanzvariable werden solche Variablen in Java mit Default-Werten (0
, 0.0
, false
) belegt.
Daneben können Variablen aber auch Zeiger (auch Pointer, oder Referenzen) enthalten. In diesem Fall zeigen die Variablen auf Objekte, die dadurch ansprechbar werden. Bei der Deklaration solcher Variablen werden diese zunächst mit dem Wert null
belegt.
Wie das genau funktioniert, lernst du in diesem interaktiven Kapitel zu Referenzen in meinem tigyog-Kurs.
Übung für deinen Gelingensnachweis #
Auf einem Handy-Sperrbildschirm sollen Benachrichtigungen angezeigt werden. Folgende Klassen sind dazu bereits entwickelt worden:
Die Klasse Benachrichtigung
#
Die Klasse Sperrbildschirm
#
Verwendung #
Betrachte den folgenden Code-Abschnitt:
Sperrbildschirm b = new Sperrbildschirm();
Benachrichtigung n = new Benachrichtigung("ByCS-Messenger", "Hi! Was warn nochmal die HA?");
b.setBenachrichtigung(n);
b.aktualisiereSperrbildschirm();
…und dessen Ergebnis:
---------------------------------
11:06
Nachricht von ByCS-Messenger:
Hi! Was warn nochmal die HA?
---------------------------------
Aufgaben #
- Nach weglassen der Zeile
b.setBenachrichtigung(n);
erscheint die Fehlermeldung
Erkläre die Fehlermeldung genau und unter Verwendung von Fachbegriffen.Fehler: Aufruf der Methode getVonApp des null-Objekts
- Als Problem wurden die folgenden beiden Zeilen aus der Methode
aktualisiereSperrbildschirm
identifiziert:Ergänze die Stelle so, dass das Problem behoben wird.String nachrichtKurz = " Nachricht von " + this.benachrichtigung.getVonApp() + ":"; nachrichtKurz += "\n " + this.benachrichtigung.getInhalt();
- Die Methode
setBenachrichtigung
in der KlasseSperrbildschirm
sieht im Augenblick wie folgt aus:Sie soll nun so umgeschrieben werden, dass eine neue Benachrichtigung erst angenommen wird, wenn die aktuelle Benachrichtigung als gelesen markiert wurde (d.h. der Aufruf der Methodepublic void setBenachrichtigung(Benachrichtigung b) { this.benachrichtigung = b; }
istGelesen
true
zurückgibt).
a) Schreibe die Methode mit den notwendigen Änderungen auf.
b) Diskutiere die Frage, ob die Benennung und der Typvoid
bei einem solchen Verhalten der Methode noch angemessen ist. Schlage ggf. einen alternativen Namen und Typ vor.
Lösungsvorschlag
- Offensichtlich ist hier versucht worden, an einem
null
-Objekt eine Methode aufzurufen. Das geschieht insbesondere dann, wenn eine Variable mit einem bestimmten Typ zwar bereits deklariert worden ist, der Variable aber noch keine Referenz auf ein entsprechendes Objekt zugewiesen wurde und dann trotzdem ein Methodenaufruf versucht wird. Weil das Objekt in einem solchen Fall nicht verfügbar ist (weil nichtexistent), können auch keine Methoden daran aufgerufen werden, und das Programm bricht mit einem Fehler ab (mit einer Null-Pointer-Exception).
(Fachbegriffe erscheinen kursiv) - Eine mögliche Verbesserung:
Erklärung:
String nachrichtKurz; if(this.benachrichtigung != null) { String nachrichtKurz = " Nachricht von " + this.benachrichtigung.getVonApp() + ":"; nachrichtKurz += "\n " + this.benachrichtigung.getInhalt(); } else { nachrichtKurz = ""; }
Mitthis.benachrichtigung != null
wird getestet, ob der Instanzvariablebenachrichtigung
bereits ein entsprechendes Objekt zugewiesen wurde. Ist dies nicht der Fall, wird der lokalen VariablenachrichtKurz
ein leerer String zugewiesen. (Da die Variable offensichtlich später verwendet wird, sollte sie sinnvoll vorhanden sein.) - a)
Erklärung:
public void setBenachrichtigung(Benachrichtigung b) { if(this.benachrichtigung == null) { this.benachrichtigung = b; } else if(this.benachrichtigung.istGelesen()) { this.benachrichtigung = b; } }
Das gewünschte Verhalten wird mitthis.benachrichtigung.istGelesen()
überprüft. Zuvor muss allerdings in irgendeiner Form überprüft werden, ob überhaupt eine Referenz auf einBenachrichtigung
s-Objekt vorliegt – dies geschieht indirekt in der Zeileif(this.benachrichtigung == null) {
– wenn dieser Vergleich nicht anschlägt, kann vom Vorhandensein eines entsprechenden Objektes ausgegangen werden.
b)
Im Prinzip kann der Typvoid
beibehalten werden, für eineSetter
-Methode wäre das typisch. In diesem Fall spricht allerdings dagegen, dass die Zuweisung einer neuen Benachrichtigung nicht immer erfolgt, und das könnte in anderen Teilen des Programms Probleme verursachen. (So müsste z.B. überprüft werden, ob die Zuweisung geklappt hat.)
Diese Überprüfung lässt sich vermeiden, wenn ein entsprechender Rückgabewert anzeigt, was der Fall ist. Naheliegend isttrue
bei Erfolg, undfalse
bei Mißerfolg. (Damit hätte die Methode den Rückgabetypboolean
.)
Auch die Benennung wäre dann anzupassen, etwa insetBenachrichtigungFallsAlteGelesen
– so würde das Verhalten der Methode klarer vorhersehbar sein.