Luisengymnasium

Array von Referenzen

Lernziele

Nach diesem Kapitel kannst du:

  • erklären, warum new Typ[n] keine n Objekte erzeugt, sondern n null-Referenzen,
  • eine Initialisierungsschleife schreiben, die alle Elemente mit new erzeugt,
  • Array-typische Fehler (NullPointerException, Off-by-One) debuggen,
  • das Speicherbild eines Referenz-Arrays zeichnen,
  • ein Programm entwerfen, das ein Array von Referenzen nutzt.

Leitfrage: Warum erzeugt new Raumschiff[5] keine fünf Raumschiffe — und wie löst du das Problem sauber?

Voraussetzungen

Hinweis

Du solltest Kapitel 01 (Referenzen, null, Aliasing) und Kapitel 02 (Speichermodell, Setter/Getter) beherrschen. Zusätzlich brauchst du: for-Schleifen und Arrays mit einfachen Werten (int[]).

Übergang aus dem Speichermodell

Bisher konnte eine Variable auf ein Objekt zeigen. Das reicht für ein Lieblingsprodukt oder einen Piloten.

Ein Lager, eine Flotte oder ein Kursraum besteht aber nicht aus einem Objekt, sondern aus vielen. Deshalb brauchen wir jetzt viele Referenzen nebeneinander.

Die neue Falle lautet: Ein Array von Referenzen erzeugt Plätze für Objekte, aber noch keine Objekte.


Phase 1: Einstieg — Die null-Falle

Hinweis

Retrieval-Check:

  1. Was ist der Unterschied zwischen int[] arr = new int[5] und Raumschiff[] arr = new Raumschiff[5]?
  2. Was passiert, wenn du auf eine null-Referenz eine Methode aufrufst?

Vorhersage

Lies den Code. Sage vorher: Funktioniert das?

Raumschiff[] flotte = new Raumschiff[3];
flotte[0].setGroesse(100);
Tipp

Denke an Kapitel 01: Was ist der Wert von flotte[0] direkt nach new Raumschiff[3]?

Teste es:

IDE lädt…


Phase 2: Konzeptaufbau — Initialisieren, dann Verarbeiten

2.1 Das Standardmuster

Bei Referenz-Arrays gibt es immer zwei Schritte:

  1. Initialisieren: Jedes Element mit new erzeugen
  2. Verarbeiten: Methoden an den Objekten aufrufen
// Schritt 1: Array + Objekte erzeugen
Raumschiff[] flotte = new Raumschiff[5];
for (int i = 0; i < flotte.length; i++)
{
    flotte[i] = new Raumschiff();   // Objekt erzeugen und eintragen
}
 
// Schritt 2: Alle Objekte verarbeiten
for (int i = 0; i < flotte.length; i++)
{
    flotte[i].setGroesse(100 + i * 50);   // Jetzt sicher — kein null mehr
    System.out.println("Schiff " + i + ": " + flotte[i].getGroesse());
}
Referenz-Array: Standardmuster
// 1. Array anlegen (nur Plätze, alle null)
Typ[] arr = new Typ[n];
 
// 2. Objekte erzeugen (Init-Schleife)
for (int i = 0; i < arr.length; i++) {
    arr[i] = new Typ();
}
 
// 3. Objekte verarbeiten
for (int i = 0; i < arr.length; i++) {
    arr[i].methode();
}

2.2 Speicherbild

Nach new Raumschiff[3]:

IndexInhalt
flotte[0]null
flotte[1]null
flotte[2]null

Nach der Initialisierungsschleife:

Mermaid-Diagramm
Mermaid-Diagramm wird geladen…

Reflexionsfrage: Was passiert, wenn du in der Verarbeitungsschleife i <= flotte.length statt i < flotte.length schreibst?

Ruhige Sicherung: Plätze sind noch keine Dinge

Tipp

Merke dir das Kapitel in genau diesem Dreischritt:

  1. new Raumschiff[3] erzeugt drei Plätze.
  2. Jeder Platz enthält zuerst null.
  3. Erst flotte[i] = new Raumschiff(...) erzeugt ein echtes Objekt.

Das Array ist also zuerst nur ein Regal. Die Raumschiffe musst du danach einzeln hineinlegen.

Probiere das Standardmuster aus:

IDE lädt…

Fading: Übe schrittweise


Phase 3: Üben

Hinweis

Retrieval-Check:

  1. Wie viele Objekte existieren nach Raumschiff[] flotte = new Raumschiff[10];?
  2. Was gibt getPilot().getName() aus, wenn kein Pilot gesetzt ist? (Rückbezug Kap. 02)

Abgabe-Aufgaben

A1: Trace — Welche Elemente sind null? (Pflicht)

Gegeben:

Raumschiff[] arr = new Raumschiff[4];
arr[0] = new Raumschiff("A");
arr[2] = new Raumschiff("C");
 
for (int i = 0; i < arr.length; i++)
{
    if (arr[i] != null)
    {
        System.out.println(i + ": " + arr[i].getName());
    }
    else
    {
        System.out.println(i + ": null");
    }
}

Schreibe die vollständige Ausgabe auf.

Textabgabe

A2: Debugging — Off-by-One und null (Pflicht)

Finde und behebe die zwei Fehler im folgenden Code:

Raumschiff[] flotte = new Raumschiff[5];
for (int i = 0; i <= flotte.length; i++)    // Fehler 1
{
    flotte[i] = new Raumschiff("Schiff " + i);
}
 
flotte[3] = null;   // Schiff 3 wurde entfernt
 
for (int i = 0; i < flotte.length; i++)
{
    flotte[i].info();    // Fehler 2
}
Textabgabe

A3: Completion — Pilot-Array (Pflicht)

Ergänze die Init-Schleife und die Ausgabe-Schleife:

IDE lädt…

A4: Design — Pilotensuche (Vertiefung)

Entwirf ein Programm mit einem Array von 5 Pilot-Objekten.

a) Schreibe die Initialisierung. b) Schreibe eine Schleife, die alle Namen ausgibt. c) Schreibe eine Methode Pilot findePilot(Pilot[] crew, String name), die den Piloten mit dem gesuchten Namen zurückgibt — oder null, falls keiner gefunden wird.

IDE lädt…

A5: Analyse — Aliasing im Array (Vertiefung)

Gegeben:

Raumschiff[] flotte = new Raumschiff[100];
flotte[0] = new Raumschiff();
flotte[1] = flotte[0];

a) Wie viele Raumschiff-Objekte existieren? b) Was gibt flotte[0].getGroesse() aus, nachdem flotte[1].setGroesse(500) aufgerufen wurde? Erkläre mit dem Aliasing-Konzept. c) Zeichne das Speicherbild.

Excalidraw lädt…


Phase 4: Transfer und Vernetzung

Transferaufgabe

Durchgängiges Projekt: Online-Shop

Diese Aufgabe ist Teil des Online-Shop-Projekts, das sich durch den Kurs Lineare Datenstrukturen 1 zieht. In Kapitel 01 hast du Produkt und Kunde kennengelernt, in Kapitel 02 den Warenkorb. Jetzt kommt das Lager dazu — ein Array von Produkt-Referenzen.

Projektstand Online-Shop

Der Shop bekommt jetzt ein Lager. Zum ersten Mal verwaltet er nicht nur ein einzelnes Produkt, sondern mehrere Produkte.

Aber dieses Lager hat eine feste Größe. Es kann leer werden, Plätze können null sein, und wenn es voll ist, wird es unbequem. Genau diese Grenze führt später zu dynamischen Datenstrukturen.

Online-Shop: Lager

Entwirf eine Klasse Lager mit einem Array von Produkt-Referenzen (feste Größe 10).

Implementiere:

  • einlagern(Produkt p) — findet den ersten freien Platz (null) und weist das Produkt zu.
  • auslagern(int platz) — setzt den Platz auf null.
  • int anzahlProdukte() — zählt alle nicht-null-Plätze.

IDE lädt…

Vernetzung

Heute gelöst: Du kannst jetzt viele Referenzen gemeinsam verwalten. Du weißt, warum ein Referenzarray anfangs nur null enthält und warum Initialisierungsschleifen notwendig sind.

Noch offen: Der Code wird langsam schwer im Kopf zu halten: Referenzen, Arrays, null, Aliasing, Speicherbilder. Bevor wir neue Datenstrukturen bauen, müssen wir lernen, solche Strukturen sichtbar und planbar zu machen.

Nächster Schritt: Das nächste Kapitel ist bewusst ein Zwischenstopp. Wir schreiben weniger neuen Code und ordnen, was wir bisher gelernt haben: mit Struktogrammen, Objektbildern und Entwurfsdiagrammen.

Reflexion

Hinweis

Beantworte die Leitfrage: Warum erzeugt new Raumschiff[5] keine fünf Raumschiffe? Erkläre mit den Begriffen „Platz", „Referenz", „null" und „Objekt".

Textabgabe

Selbstdiagnose

  • Ich weiß, dass new Typ[n] nur null-Plätze erzeugt.
  • Ich kann eine Initialisierungsschleife schreiben.
  • Ich kann Off-by-One-Fehler in Array-Schleifen erkennen.
  • Ich kann Aliasing in Arrays erklären.