MINT lernen

Übungen: Reihungen von Objekten

Eine Reihung von Objekten ist erst einmal eine Reihe leerer Plätze voller null — gefüllt wird sie Objekt für Objekt mit new.

Dein Fortschritt:
0 / 0 Aufgaben
1

Übungsaufgaben

Zehn Übungen zum Klicken, Ziehen und Knobeln — von AFB I bis AFB III. Jede Übung gibt dir sofort Rückmeldung; wenn du hängst, helfen dir die gestuften Tipps.

A1
Routen in der Kletterhalle
AFB I

Eine Kletterhalle verwaltet ihre Routen. Die Klasse Route hat den Konstruktor Route(name, schwierigkeit) und die Methode getSchwierigkeit(). Welche Aussagen über diese Zeile stimmen?

Route[] routen = new Route[5];
Mehrere Antworten sind richtig. Markiere alle zutreffenden und klicke dann auf „Prüfen“.
new Route[5] ruft keinen Konstruktor der Klasse Route auf — es erzeugt nur die Reihung mit fünf leeren Plätzen für Referenzen. Jede Route muss einzeln mit new Route(...) erzeugt werden. Die Indizes laufen von 0 bis 4. Ein Methodenaufruf an einem leeren Platz führt zur NullPointerException — es gibt dort kein Objekt, das 0 liefern könnte.
Ansatz: Frage dich: Wird hier ein Konstruktor der Klasse Route aufgerufen? Welche Klammern stehen hinter new Route?
Weiter: Eckige Klammern erzeugen die Reihung, runde Klammern erzeugen ein Objekt. Leere Plätze einer Objekt-Reihung sind null.
A2
Die Getränkekiste
AFB I

Ein Getränkemarkt verwaltet Kisten als Reihung von Flaschen. Die Klasse Flasche hat den Konstruktor Flasche(sorte, inhaltMl), getInhalt() und leeren(). Was bewirkt jede Zeile?

Ziehe jede Karte in den passenden Korb — oder wähle sie mit Enter aus und drücke dann die Ziffer des Korbs (0 legt sie zurück).
1legt nur leere Plätze an
2erzeugt ein neues Objekt
3nutzt ein vorhandenes Objekt
Nur new Flasche(...) mit runden Klammern erzeugt eine Flasche; new Flasche[12] mit eckigen Klammern erzeugt die Kiste mit zwölf leeren Plätzen. Typischer Fehler: kiste[1] = kiste[0]; für eine neue Flasche halten. Es wird aber nur die Referenz kopiert — Platz 1 und Platz 0 zeigen auf dieselbe Flasche. Wer danach kiste[0].leeren() aufruft, leert beide Plätze.
Ansatz: Achte bei jedem new auf die Klammern: eckig oder rund?
Weiter: Eine Zuweisung von einem Platz zum anderen kopiert nur den Verweis. Ein Methodenaufruf nutzt ein Objekt, das schon da ist.
A3
Beete im Schulgarten
AFB I

Die Garten-AG hat acht Plätze für Beete, aber noch nicht alle angelegt: Beet[] beete = new Beet[8]; Die Methode getFlaeche() liefert die Fläche eines Beetes in m². Vervollständige die Summe über alle angelegten Beete — ein Kärtchen bleibt übrig.

Wort anklicken, dann Lücke anklicken (oder umgekehrt) — mit Tab und Enter geht es genauso. Ein Klick auf eine gefüllte Lücke legt das Wort zurück.

int summe = ;
for (int i = 0; i < beete.; i++) {
if (beete[i] ) {
summe = summe + beete[i].();
} }

length() mit Klammern bleibt übrig: Das ist die Methode von Zeichenketten. Bei Reihungen ist length ein Attribut ohne Klammern (Kapitel 2). Die Prüfung beete[i] != null ist Pflicht, weil noch nicht alle Plätze ein Beet enthalten — ohne sie bricht die Schleife am ersten leeren Platz mit einer NullPointerException ab.
Ansatz: Wie oft soll die Schleife laufen? Und was steht an den Plätzen, an denen noch kein Beet angelegt ist?
Weiter: Nur wenn an Platz i wirklich ein Objekt ist, darf man seine Methode aufrufen.
A4
Stimmt's? — Das Fotoalbum
AFB II

Eine Foto-App speichert Fotos mit Sternebewertung (Getter und Setter für sterne).

Foto[] album = new Foto[4];
album[0] = new Foto("Strand", 3);
album[2] = new Foto("Watt", 5);
album[3] = album[0];
Fünf Aussagen nacheinander. Eine falsche Einschätzung reicht — dann startest du die Serie mit „Neue Runde“ neu.
Aussage 1 von 5

In einer Reihung von Objekten stehen Referenzen. Zwei Plätze können auf dasselbe Objekt verweisen, und leere Plätze sind null. Darum gehört beim Durchlaufen fast immer eine Prüfung album[i] != null in die Schleife.
Ansatz: Zeichne die vier Plätze als Kästchen und die Foto-Objekte daneben. Ziehe Pfeile von den Plätzen zu den Objekten.
Weiter: Zähle die new Foto(...). Und length zählt Plätze, nicht Objekte.
A5
Ein Rezept mit Zutaten
AFB II

Eine Koch-App speichert die Zutaten eines Rezepts in einer Reihung. Die Klasse Zutat hat den Konstruktor Zutat(name, menge) sowie getName() und getMenge(). Verbinde jede Aufgabe mit dem passenden Java-Baustein.

Ansatz: Ordne zuerst die beiden Zeilen mit new zu: Welche erzeugt die Reihung, welche ein Objekt?
Weiter: Index = Position − 1. Und leere Plätze erkennt man am Wert null.
A6
Der Solarpark auf dem Schuldach
AFB IIMix

Auf dem Schuldach sind Plätze für sechs Solarmodule. Die Klasse Modul hat getLeistung() (in Watt), defektMelden() und istDefekt(). Die Bedingung in der Schleife verknüpft zwei Teilbedingungen wie in Kapitel 1.

Modul[] park = new Modul[6];
park[0] = new Modul(320);
park[1] = new Modul(410);
park[3] = new Modul(380);
park[4] = new Modul(290);
park[4].defektMelden();

int summe = 0;
for (int i = 0; i < park.length; i++) {
    if (park[i] != null && !park[i].istDefekt()) {
        summe = summe + park[i].getLeistung();
    }
}

Welchen Wert hat summe nach der Schleife (in Watt)?

Rechne selbst und trage das Ergebnis ein — Enter prüft direkt.
Gezählt werden nur Plätze, an denen ein Modul steht und das Modul nicht defekt ist: 320 + 410 + 380 = 1110. Platz 4 fällt wegen des Defekts heraus, die Plätze 2 und 5 sind leer. Wichtig ist die Reihenfolge der Teilbedingungen: Bei && wird die rechte Seite nur ausgewertet, wenn die linke wahr ist. Stünde !park[i].istDefekt() vorn, gäbe es an Platz 2 eine NullPointerException. Häufige Fehler: 1400 (Defekt übersehen) oder 290 (das Ausrufezeichen übersehen — dann zählte ausgerechnet nur das defekte Modul).
Ansatz: Gehe die sechs Plätze einzeln durch: Ist der Platz belegt? Ist das Modul in Ordnung?
Weiter: Nur park[4] ist defekt. Die Plätze 2 und 5 sind null und werden durch die erste Teilbedingung übersprungen.
A7
Zelte im Ferienlager
AFB II

Im Ferienlager werden die Zelte in einer Reihung verwaltet.

public class Zelt {
    private String name;
    private int plaetze;
    private int belegt;

    public Zelt(String name, int plaetze) {
        this.name = name;
        this.plaetze = plaetze;
        belegt = 0;
    }

    public void aufnehmen(int personen) {
        belegt = belegt + personen;
    }

    public int getBelegt() {
        return belegt;
    }

    public int getFrei() {
        return plaetze - belegt;
    }
}
Zelt[] zelte = new Zelt[5];
zelte[0] = new Zelt("Adler", 4);
zelte[1] = new Zelt("Biber", 9);
zelte[3] = new Zelt("Dachs", 4);
zelte[4] = zelte[1];
zelte[4].aufnehmen(2);
zelte[0].aufnehmen(3);
zelte[1].aufnehmen(1);

Sortiere die Ausdrücke nach ihrem Wert am Ende — der kleinste zuerst.

Ziehe die Karten in die richtige Reihenfolge — mit der Tastatur: ↑/↓ verschiebt, Shift+↑/↓ wechselt nur den Fokus.
1zelte[0].getFrei()
2zelte[4].getBelegt()
3zelte[3].getFrei()
4zelte.length
5zelte[1].getFrei()
Werte: zelte[0].getFrei() = 4 − 3 = 1, zelte[4].getBelegt() = 2 + 1 = 3, zelte[3].getFrei() = 4, zelte.length = 5, zelte[1].getFrei() = 9 − 3 = 6. Der Knackpunkt ist Platz 4: Er verweist auf dasselbe Zelt „Biber“ wie Platz 1. Beide aufnehmen-Aufrufe landen im selben Objekt. Wer zelte[4] für ein eigenes Zelt hält, kommt auf belegt = 2 und frei = 8. Und zelte.length ist 5, obwohl nur drei Zelte existieren.
Ansatz: Lege für jedes Zelt-Objekt eine kleine Objektkarte an. Wie viele Objekte gibt es wirklich?
Weiter: zelte[4] und zelte[1] sind dasselbe Objekt „Biber“: belegt = 2 + 1.
A8
Honig vom Bienenstand
AFB III

Eine Imker-AG führt ihre Bienenvölker in einer Reihung. ernten(kg) entnimmt Honig, getHonig() liefert den Vorrat in kg.

public class Bienenvolk {
    private String name;
    private int honig;

    public Bienenvolk(String name, int honig) {
        this.name = name;
        this.honig = honig;
    }

    public void ernten(int kg) {
        honig = honig - kg;
    }

    public int getHonig() {
        return honig;
    }
}
Bienenvolk[] stand = new Bienenvolk[6];
stand[0] = new Bienenvolk("Linde", 12);
stand[1] = new Bienenvolk("Raps", 18);
stand[2] = new Bienenvolk("Klee", 15);
stand[4] = new Bienenvolk("Heide", 15);
stand[5] = stand[1];
stand[2].ernten(4);

int summe = 0;
int maxIndex = 0;
for (int i = 0; i < stand.length; i++) {
    if (stand[i] != null) {
        summe = summe + stand[i].getHonig();
        if (stand[i].getHonig() > stand[maxIndex].getHonig()) {
            maxIndex = i;
        }
    }
}
stand[5].ernten(2);
Rechne die Kette Schritt für Schritt: Erst wenn ein Schritt stimmt, wird der nächste freigeschaltet. Enter prüft.
  1. Wie viele Bienenvolk-Objekte gibt es? Objekte
  2. Wert von summe nach der Schleife kg
  3. Wert von maxIndex nach der Schleife
  4. Rückgabewert von stand[1].getHonig() ganz am Ende kg
Es gibt vier new Bienenvolk(...); Platz 3 ist leer, Platz 5 verweist auf „Raps“. Die Schleife addiert deshalb Raps zweimal: 12 + 18 + 11 + 15 + 18 = 74 — eine Summe über Plätze ist nicht dasselbe wie eine Summe über Objekte. Das Maximum 18 wird zuerst an Index 1 gefunden; an Index 5 ist 18 > 18 falsch, maxIndex bleibt 1. stand[5].ernten(2) wirkt auf dasselbe Objekt wie stand[1]: 18 − 2 = 16. Typische Fehler: 56 (Raps nur einmal), 5 (maxIndex beim zweiten Treffer) und 18 (Alias übersehen).
Ansatz: Lege eine Tabelle mit den Plätzen 0 bis 5 an und notiere, auf welches Volk jeder Platz zeigt und wie viel Honig es hat.
Weiter: Klee hat nach dem Ernten 11 kg. Der Vergleich mit > ersetzt maxIndex nur bei einem echt größeren Wert.
A9
Fehlersuche: Der Bootsverleih am See
AFB III

Ein Bootsverleih hat zehn Liegeplätze, die nach und nach mit Booten belegt werden. anzahlFrei() soll zählen, wie viele Boote gerade frei sind; hinzufuegen soll ein schon erzeugtes Boot an einen Liegeplatz legen. Die Klasse Boot:

Boot
  • - name: Zeichenkette
  • - frei: Wahrheitswert
  • c Boot(name: Zeichenkette)
  • + istFrei(): Wahrheitswert
  • + verleihen()

In der Klasse Bootsverleih stecken drei Fehler.

In diesem Text stecken Fehler. Klicke genau die falschen Zeilen an — die richtigen musst du stehen lassen.
Die Zeile boote = new Boot[10]; im Konstruktor ist richtig: Sie legt nur die zehn leeren Liegeplätze an — die Boote kommen später über hinzufuegen. Die beiden Fehler in anzahlFrei sind die Klassiker beim Durchlaufen einer Objekt-Reihung: Indexgrenze und fehlende null-Prüfung.
Ansatz: Prüfe die Schleife zweimal: Stimmt die Grenze? Und darf man an jedem Platz eine Methode aufrufen?
Weiter: Der letzte gültige Index ist length − 1. In hinzufuegen soll kein neues Boot entstehen — es ist schon da.
A10
Trickaufgabe: Luftballons für die Abifeier
AFB IIITrick

Für die Deko der Abifeier wird eine Kette aus vier Luftballons programmiert. Nach diesem Code stehen alle Zeilen unten — jede Zeile startet wieder direkt nach dem Code. Welchen Wert liefert der letzte Ausdruck der Zeile?

public class Luftballon {
    private int luft;

    public Luftballon() {
        luft = 0;
    }

    public void aufblasen() {
        luft = luft + 1;
    }

    public int getLuft() {
        return luft;
    }
}
Luftballon[] kette = new Luftballon[4];
Luftballon b = new Luftballon();
for (int i = 0; i < kette.length; i++) {
    kette[i] = b;
}
kette[0].aufblasen();
kette[3].aufblasen();
Wähle für jede Zeile eine Stufe: 0 = Wert 0, 1 = Wert 1, 2 = Wert 2, 3 = Wert 3, 4 = Wert 4. Mit der Tastatur: Tab zur Zeile, ←/→ zwischen den Stufen, Enter setzt.
0 = Wert 04 = Wert 4
kette[1].getLuft()
Anzahl der erzeugten Luftballon-Objekte
kette.length
kette[2] = new Luftballon(); kette[2].getLuft()
kette[3] = null; kette[0].aufblasen(); b.getLuft()
Der Trick: new Luftballon() steht vor der Schleife. Die Schleife verteilt also nur viermal dieselbe Referenz — alle vier Plätze zeigen auf einen einzigen Ballon. Deshalb landen beide aufblasen-Aufrufe im selben Objekt, und auch kette[1] liefert 2. Erst kette[2] = new Luftballon() erzeugt einen zweiten Ballon (mit 0). Und kette[3] = null löscht nur einen Verweis, nicht den Ballon: Er bekommt über kette[0] noch einmal Luft, b.getLuft() = 3. Korrekt wäre kette[i] = new Luftballon(); in der Schleife.
Ansatz: Wie oft wird der Konstruktor Luftballon() aufgerufen — also wie oft steht new Luftballon() in einer ausgeführten Zeile?
Weiter: Alle Plätze zeigen auf dasselbe Objekt b. Jede Änderung über irgendeinen Platz ist auch über b sichtbar.