MINT lernen

Übung — AFB I (Reproduzieren)

Zehn Grundaufgaben quer durch das Java-Kapitel — wer sie sicher löst, hat die ersten Punkte der Arbeit schon in der Tasche.

Dein Fortschritt:
0 / 0 Aufgaben
1

Aufgabenblock — AFB I

Zehn Standardaufgaben zum Reproduzieren, bunt gemischt aus allen elf Unterkapiteln: Programme Zeile für Zeile verfolgen, Typen und Werte angeben, Klassenkarten zeichnen, Arrays und Listen auslesen. Das sind die sicheren Punkte in jeder Arbeit — eine der zehn Aufgaben ist allerdings eine Trickaufgabe.

A1
Vom Quelltext zur Ausgabe: Kinokasse
AFB I

Das Programm einer Kinokasse liegt in der Datei Kinokasse.java:

public class Kinokasse {
    public static void main(String[] args) {
        System.out.print("Saal ");
        System.out.println(3);
        System.out.print("Reihe ");
        System.out.print(7);
        System.out.println(", Platz 12");
        System.out.println("Viel Spaß im Film!");
    }
}

Nenne den Befehl zum Übersetzen, den Namen der Datei, die dabei entsteht, und den Befehl zum Starten. Wie viele Zeilen erscheinen in der Konsole?

Ansatz: javac übersetzt die ganze Datei vorab in Bytecode. Die Bytecode-Datei trägt den Klassennamen und die Endung .class.
Zeilen zählen: Nur println beendet die Zeile. print schreibt in derselben Zeile weiter.
Vollständige Lösung

Übersetzen: javac Kinokasse.java → es entsteht Kinokasse.class (Bytecode). Starten: java Kinokasse — ohne Endung, die JVM führt den Bytecode aus.

Ausgabe (3 Zeilen):

Saal 3
Reihe 7, Platz 12
Viel Spaß im Film!

Wer 5 Zeilen zählt, hat jedes print als eigene Zeile gewertet.

A2
Trickaufgabe — Sammelkarten gerecht verteilen
AFB I

Fünf Freunde teilen 47 Sammelkarten gleichmäßig auf. Außerdem will das Programm wissen, was „die Hälfte aller Karten“ ist.

int karten = 47;
int spieler = 5;
int proKopf = karten / spieler;
int rest = karten % spieler;
double haelfte = karten / 2;

Berechne die Werte der drei Variablen, so wie Java sie speichert.

Ansatz: / zwischen zwei int-Werten ist eine Ganzzahldivision: Nachkommastellen werden abgeschnitten. % liefert den Rest.
Reihenfolge: Erst wird rechts gerechnet, dann gespeichert. Welchen Typ haben karten und 2? Das Umwandeln in double passiert erst danach.
Vollständige Lösung

47 / 5 → 9 (9 · 5 = 45), 47 % 5 → 2 Karten bleiben übrig.

Die Falle: karten / 2 ist int / int = 23. Erst dieses Ergebnis wird automatisch zu double erweitert: haelfte = 23.0, nicht 23.5. Richtig wäre karten / 2.0 oder (double) karten / 2.

A3
for-Schleife mit if: Countdown
AFB I

Ein Modellraketen-Club zählt beim Start in Dreierschritten herunter:

int durchlaeufe = 0;
for (int i = 20; i > 0; i -= 3) {
    if (i % 2 == 0) {
        System.out.println(i + " gerade");
    } else {
        System.out.println(i);
    }
    durchlaeufe++;
}
System.out.println("Start!");

Wende die Schleife Schritt für Schritt an: Wie oft läuft sie, welche Zahl steht in der letzten Zahlenzeile, und wie viele Zeilen enden mit „gerade“?

Ansatz: Schreibe die Werte von i untereinander: Start 20, dann jeweils 3 weniger, solange i > 0 gilt.
Bedingung: i % 2 == 0 ist genau dann wahr, wenn i ohne Rest durch 2 teilbar ist.
Vollständige Lösung

i durchläuft 20, 17, 14, 11, 8, 5, 2 → 7 Durchläufe. Danach wäre i = −1, die Bedingung i > 0 ist falsch. Letzte Zahl: 2.

Gerade sind 20, 14, 8 und 2 → 4 Zeilen mit „gerade“. In Python hieße der Kopf for i in range(20, 0, -3):.

A4
Methode mit Rückgabe: Weitsprung-Punkte
AFB I

Beim Sportfest bekommt man ab 2 m Weite für je 10 cm einen Punkt:

public static int punkte(int weiteCm) {
    if (weiteCm < 200) {
        return 0;
    }
    return (weiteCm - 200) / 10;
}

In main steht: int summe = punkte(356) + punkte(190) + punkte(410);

Gib den Rückgabetyp, den Parameter mit Typ und den Wert von summe an.

Ansatz: Der Rückgabetyp steht direkt vor dem Methodennamen, der Parameter in der Klammer. Rechne jeden der drei Aufrufe einzeln aus.
Achtung: 156 / 10 ist in Java 15 — der Rest fällt weg. Und return beendet die Methode sofort.
Vollständige Lösung

Rückgabetyp int, Parameter int weiteCm.

punkte(356) → 156 / 10 = 15; punkte(190) → 190 < 200, also 0; punkte(410) → 210 / 10 = 21. summe = 15 + 0 + 21 = 36.

A5
Zwei Konstruktoren: Zelte im Outdoorladen
AFB I

Ein Outdoorladen verwaltet seine Zelte mit dieser Klasse:

public class Zelt {
    private String marke;
    private int personen;
    private boolean aufgebaut;
    private double gewichtKg;

    public Zelt(String marke, int personen) {
        this.marke = marke;
        this.personen = personen;
    }

    public Zelt(String marke) {
        this.marke = marke;
        personen = 2;
        gewichtKg = 1.8;
    }
}

Erzeugt werden Zelt z1 = new Zelt("Nordwind", 4); und Zelt z2 = new Zelt("Kiesel");

Entnimm dem Quelltext die Attributwerte der beiden Objekte direkt nach dem Erzeugen.

Ansatz: Welcher Konstruktor läuft, entscheidet die Anzahl und Art der Argumente: zwei Werte → erster Konstruktor, ein Wert → zweiter.
Standardwerte: Attribute, die kein Konstruktor setzt, behalten ihren Startwert: 0, 0.0, false bzw. null.
Vollständige Lösung
z1: Zelt
  • marke = "Nordwind"
  • personen = 4
  • aufgebaut = false
  • gewichtKg = 0.0
z2: Zelt
  • marke = "Kiesel"
  • personen = 2
  • aufgebaut = false
  • gewichtKg = 1.8

z1 nutzt den Konstruktor mit zwei Parametern; gewichtKg wird dort nicht gesetzt und bleibt beim Standardwert 0.0. z2 nutzt den überladenen Konstruktor mit einem Parameter: personen = 2. aufgebaut setzt keiner der beiden — also jeweils false.

z2: Zelt
  • marke = ?
  • personen = ?
  • aufgebaut = ?
  • gewichtKg = ?
Objektkarte zum Ausfüllen
A6
Vom Quelltext zur Klassenkarte: Trinkflasche
AFB I

Eine App erinnert ans Trinken. Sie enthält diese Klasse:

public class Trinkflasche {
    private String farbe;
    private int kapazitaetMl;
    private int fuellungMl;
    private boolean isoliert;

    public Trinkflasche(String farbe, int kapazitaetMl) {
        this.farbe = farbe;
        this.kapazitaetMl = kapazitaetMl;
        fuellungMl = kapazitaetMl;
        isoliert = false;
    }

    public void trinken(int ml) {
        int rest = fuellungMl - ml;
        if (rest >= 0) {
            fuellungMl = rest;
        }
    }

    public int getFuellungMl() {
        return fuellungMl;
    }

    public boolean istLeer() {
        return fuellungMl == 0;
    }

    public void setIsoliert(boolean isoliert) {
        this.isoliert = isoliert;
    }
}

Zeichne die zugehörige Klassenkarte in der Notation aus dem Unterricht.

Ansatz: Drei Fächer: Name — Attribute — Konstruktor und Methoden. private wird -, public wird +, der Konstruktor bekommt ein c.
Achtung: rest ist eine lokale Variable in trinken — kein Attribut. void lässt du weg, Typen übersetzt du: int → Ganzzahl, boolean → Wahrheitswert, String → Zeichenkette.
Vollständige Lösung
Trinkflasche
  • - farbe: Zeichenkette
  • - kapazitaetMl: Ganzzahl
  • - fuellungMl: Ganzzahl
  • - isoliert: Wahrheitswert
  • c Trinkflasche(farbe: Zeichenkette, kapazitaetMl: Ganzzahl)
  • + trinken(ml: Ganzzahl)
  • + getFuellungMl(): Ganzzahl
  • + istLeer(): Wahrheitswert
  • + setIsoliert(isoliert: Wahrheitswert)

Vier Attribute, ein Konstruktor, vier Methoden. Die Anweisungen in den Rümpfen (return fuellungMl;, int rest = …) gehören nicht ins Diagramm.

A7
Setter mit Prüfung: Akku eines E-Bikes
AFB I

Der Ladestand eines E-Bike-Akkus darf nur 0 bis 100 % betragen. Ungültige Werte weist der Setter ab.

public class Akku {
    private int ladung;

    public Akku() {
        ladung = 50;
    }

    public int getLadung() {
        return ladung;
    }

    public void setLadung(int ladung) {
        if (ladung >= 0 && ladung <= 100) {
            this.ladung = ladung;
        }
    }

    public void laden(int prozent) {
        setLadung(ladung + prozent);
    }
}
Akku a = new Akku();
a.setLadung(120);
a.setLadung(35);
a.laden(40);
a.laden(40);
a.setLadung(-5);

Bestimme den Wert von ladung nach allen Aufrufen und die Anzahl der abgewiesenen Aufrufe.

%
Ansatz: Führe eine Tabelle: Aufruf — gewünschter Wert — gültig? — ladung danach. Der Startwert kommt aus dem Konstruktor.
laden: laden(40) ruft intern setLadung(ladung + 40) auf — auch dieser Wert geht also durch die Prüfung. Abgewiesen heißt: Der alte Wert bleibt, er wird nicht auf 100 gekappt.
Vollständige Lösung

50 → setLadung(120) abgewiesen: 50 → setLadung(35): 35 → laden(40): 75 → laden(40) will 115, abgewiesen: 75 → setLadung(-5) abgewiesen: 75 %.

3 Aufrufe wurden abgewiesen. Ein direkter Zugriff a.ladung = 90; würde gar nicht übersetzt: ladung has private access in Akku.

Akku
  • - ladung: Ganzzahl
  • c Akku()
  • + getLadung(): Ganzzahl
  • + setLadung(ladung: Ganzzahl)
  • + laden(prozent: Ganzzahl)
Klassenkarte der Klasse Akku
A8
Array füllen: Tore der Saison
AFB I

Eine Handball-AG speichert die Tore der ersten sechs Spiele in einem Array. Die Werte entstehen so:

int[] tore = new int[6];
tore[0] = 2;
for (int i = 1; i < tore.length; i++) {
    tore[i] = tore[i - 1] + i;
}
tore[4] = tore[4] % 3;

Trage die Werte der Fächer 3, 4 und 5 nach dem Programmende in die Fächerreihe ein.

Ansatz: Jedes Fach ist „Vorgänger plus Index“: tore[1] = tore[0] + 1, tore[2] = tore[1] + 2 usw.
Reihenfolge: Die letzte Zeile läuft erst, wenn die Schleife fertig ist. tore[5] wurde also mit dem alten Wert von tore[4] berechnet.
Vollständige Lösung

Schleife: 2 → 2 + 1 = 3 → 3 + 2 = 5 → 5 + 3 = 8 → 8 + 4 = 12 → 12 + 5 = 17. Danach tore[4] = 12 % 3 = 0. tore[5] bleibt 17.

012345
2358017

tore.length ist 6, der größte Index also 5. Ein Zugriff auf tore[6] würde eine ArrayIndexOutOfBoundsException auslösen.

012345
235???
Fächerreihe tore mit Index darüber
A9
ArrayList und lineare Suche: Fundbüro
AFB I

Das Fundbüro der Schule führt eine Liste. Die Methode finde sucht von vorne und zählt ihre Vergleiche mit equals.

ArrayList<String> fund = new ArrayList<>();
fund.add("Schal");
fund.add("Brotdose");
fund.add("Turnbeutel");
fund.add("Regenschirm");
fund.remove(1);
fund.set(2, "Handschuh");
fund.add("Fahrradhelm");

Stelle den Inhalt der Liste nach jeder Anweisung in einer Tabelle dar. Trage unten fund.size() am Ende ein und wie viele Vergleiche die Suche nach „Handschuh“ bzw. nach „Brotdose“ braucht.

Ansatz: remove(1) entfernt das Element an Index 1, die folgenden rücken nach vorne. set(2, …) überschreibt, ohne die Größe zu ändern.
Suche: Gezählt wird jeder Vergleich bis zum Treffer. Fehlt das Gesuchte, muss die Suche alle Einträge ansehen.
Vollständige Lösung

4 × add: [Schal, Brotdose, Turnbeutel, Regenschirm]
remove(1): [Schal, Turnbeutel, Regenschirm]
set(2, "Handschuh"): [Schal, Turnbeutel, Handschuh]
add("Fahrradhelm"): [Schal, Turnbeutel, Handschuh, Fahrradhelm] → size() = 4

„Handschuh“ steht an Index 2 → Vergleiche mit Schal, Turnbeutel, Handschuh = 3. „Brotdose“ wurde entfernt → alle 4 Einträge werden verglichen, die Suche meldet „nicht gefunden“.

A10
Geerbt, neu oder überschrieben? Musikinstrumente
AFB I

Eine Musikschule verwaltet ihre Instrumente:

public class Instrument {
    private String name;

    public Instrument(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public String klang() {
        return "...";
    }
}

public class Trommel extends Instrument {
    private int durchmesserCm;

    public Trommel(String name, int durchmesserCm) {
        super(name);
        this.durchmesserCm = durchmesserCm;
    }

    public int getDurchmesserCm() {
        return durchmesserCm;
    }

    @Override
    public String klang() {
        return "Bumm";
    }
}

Ordne jede Methode, die ein Trommel-Objekt aufrufen kann, einer Gruppe zu: geerbt, neu oder überschrieben. Was liefert new Trommel("Cajon", 30).klang()?

Ansatz: extends heißt: Alles Öffentliche aus Instrument hat die Trommel auch. Steht eine Methode mit gleicher Signatur in beiden Klassen, ist sie überschrieben.
Regel: Es läuft immer die Methode der Klasse, zu der das Objekt gehört — hier also die aus Trommel.
Vollständige Lösung

geerbt: getName() · neu: getDurchmesserCm() · überschrieben: klang() (mit @Override).

new Trommel("Cajon", 30).klang() liefert "Bumm". Das Attribut name besitzt die Trommel zwar auch, sie darf es aber nicht direkt lesen: t.name ergibt name has private access in Instrument — deshalb super(name) im Konstruktor und getName() zum Lesen.