Alle Tabs der Lerneinheit (Erklärung · Interaktiv · Quiz) als durchgehender Text. Ideal zum Wiederholen vor der Klausur, und für Suchmaschinen wie Google, Bing und KI-Suche (ChatGPT, Perplexity).
Erklärung
Funktionen (Methoden)
Eine Funktion ist ein wiederverwendbarer benannter Codeblock, der Eingaben (Parameter) entgegennimmt und optional ein Ergebnis zurückgibt. Für die Grundidee sind Funktionen und Methoden ähnlich; fachlich: Java arbeitet primär mit Methoden in Klassen (statische und Instanz-Methoden), Python kennt sowohl freie Funktionen (also Funktionen außerhalb einer Klasse) als auch Methoden in Klassen. Du lernst hier, Funktionen zu schreiben, Aufrufe Schritt für Schritt zu verfolgen, Parameter sauber von Rückgabewerten zu trennen und die häufigsten Klausurfallen (Signatur, call-by-value, mehrere return-Pfade) zu vermeiden. Das ist Pflichtstoff im 1. Semester Informatik, Wirtschaftsinformatik und allen verwandten Studiengängen.
Die vier Kern-Elemente einer Funktion:
- Name (Pflicht): wie die Funktion aufgerufen wird, z. B.
berechneSumme - Parameter (optional, Eingaben):
- Java: Typ + Name, z. B.
(int a, int b) - Python: nur Namen; Typannotationen sind optional, z. B.
def add(a: int, b: int) -> int:
- Java: Typ + Name, z. B.
- Rückgabewert (optional): Datentyp des Ergebnisses, z. B.
intodervoidwenn nichts zurückkommt - Body (Pflicht):
- Java: Code zwischen
{ ... } - Python: eingerückter Block nach
def ...:
- Java: Code zwischen
In Klausuren wirst du oft gefragt: schreibe eine Funktion die [Anforderung]. Wichtig ist die Java-Signatur = Methodenname + Parametertypen in Reihenfolge. Der Rückgabetyp gehört zur Methodendeklaration, nicht zur Signatur im Sinne von Overloading (zwei Methoden mit gleichem Namen + gleichen Parametern dürfen sich nicht nur durch Rückgabetyp unterscheiden). Fortgeschrittenen-Detail: bei generischen Methoden gehören per Java Language Specification (§8.4.2) auch die Typ-Parameter zur formalen Signatur; für Einsteiger-Klausuren reicht die Sicht oben.
Java ist immer call-by-value. Bei primitiven Typen wird der Wert kopiert. Bei Objekten wird die Referenz als Wert kopiert: Mutationen am Objekt können von außen sichtbar sein, aber eine Neuzuweisung des Parameters ändert nicht die Variable im Aufrufer.
Aufbau
Eine Funktion hat:
- einen Namen
- Parameter (Eingabe, optional)
- einen Rückgabewert (Ausgabe, optional)
- einen Körper (was sie tut)
public static int quadrat(int x) {
return x * x;
}
// Aufruf
int ergebnis = quadrat(5); // ergebnis ist 25def quadrat(x):
return x * x
# Aufruf
ergebnis = quadrat(5) # ergebnis ist 25Lesart: quadrat ist eine Funktion, die ein int als Eingabe nimmt und ein int zurückgibt. Sie multipliziert die Eingabe mit sich selbst.
Was beim Aufruf passiert (Stack-Frame Schritt für Schritt)
int ergebnis = quadrat(5); läuft intern in fünf Schritten ab und genau diese Sequenz solltest du in der Klausur traceln können:
- Argument auswerten: der Ausdruck
5wird zu5ausgewertet. - Stack-Frame anlegen: die JVM (oder Python-VM) legt einen neuen Frame auf dem Call-Stack an. Im Frame leben Parameter und lokale Variablen der Funktion.
- Parameter kopieren: der Wert
5wird in den Parameterxkopiert. Im Frame steht jetztx = 5. - Body ausführen:
return x * xrechnet5 * 5 = 25und liefert den Wert an den Aufrufer. - Frame zerstören, Rückgabewert zuweisen: der Frame wird vom Stack genommen,
ergebnisbekommt25. Der Parameterxexistiert nicht mehr.
Im nachfolgenden Interaktiv-Abschnitt ist genau dieses Verhalten als Code-Stepper aufbereitet (verdoppeln, mutateList, reassignList, absolutBetrag) inklusive sichtbarem Call-Stack.
Scope: Parameter und lokale Variablen sind lokal
Scope bedeutet: in welchem Bereich des Programms ein Name sichtbar/gültig ist.
- Parameter sind nur innerhalb der Funktion sichtbar. Ein Name wie
xin der Funktion und einxaußerhalb sind zwei verschiedene Variablen. - Lokale Variablen (im Body deklariert) existieren nur bis zum Funktionsende, danach werden sie zusammen mit dem Frame zerstört.
- Java: Scope endet mit dem nächsten
}. Innerhalb eines Methoden-Blocks gilt Block-Scope. - Python: Scope ist immer die ganze Funktion (kein Block-Scope für
if/forinnerhalb einer Funktion). Funktionen, Klassen, Module und Comprehensions haben jeweils eigene Scope-Regeln. Klausur-Falle: in Python istfor i in range(...):deklariert kein Block-lokalesi, dasiexistiert nach der Schleife weiter.
public static int verdoppeln(int x) {
return x * 2;
}
int x = 5;
int y = verdoppeln(x); // x außen bleibt 5, das x in verdoppeln ist eine Kopie
Mehrere return-Pfade und Guard-Clauses
Eine Funktion kann mehrere return-Anweisungen haben. Sobald eines erreicht wird, endet die Funktion sofort. In gut lesbarem Code werden mehrere returns gezielt eingesetzt (Guard-Clauses, klare Fallunterscheidungen), nicht beliebig verstreut. In Klausuren ist das Tracing wichtig: welcher Pfad wird genommen, was wird zurückgegeben?
public static int absolutBetrag(int x) {
if (x < 0) return -x; // Guard für negative Werte
return x; // Happy Path
}
Ein Guard-Clause (Wächter-Anweisung) prüft am Anfang einer Funktion einen Sonderfall und kehrt früh zurück. Vorteile: spart Verschachtelung, der Happy-Path bleibt eingerückt-frei und lesbar.
Warum Funktionen?
- Wiederverwendung: einmal schreiben, oft benutzen.
- Lesbarkeit:
berechneFlaeche(5, 3)ist klarer als5 * 3. - Fehler isolieren: wenn die Berechnung falsch ist, musst du sie nur an einer Stelle fixen.
- Testbarkeit: kleine, fokussierte Funktionen lassen sich isoliert testen.
void: Funktionen ohne Rückgabe
Funktionen müssen nicht immer etwas zurückgeben.
- Java:
voidheißt kein Rückgabewert. Du kannst mitreturn;(ohne Wert) die Methode vorzeitig verlassen, aber niemalsreturn wert;. - Python: ohne explizites
returnwird automatischNonezurückgegeben, das ist ein echter Wert, nicht exakt dasselbe wie Java-void.
Default-Parameter: Python ja, Java nein
Python erlaubt Default-Werte für Parameter direkt in der Signatur, Java nicht. Wer in Java optionale Parameter braucht, simuliert das per Overloading (mehrere Methoden mit gleichem Namen, unterschiedlicher Parameter-Liste).
def greet(name="Gast"):
print(f"Hallo {name}")
greet() # Hallo Gast
greet("Anna") # Hallo Anna
public static void greet() {
greet("Gast");
}
public static void greet(String name) {
System.out.println("Hallo " + name);
}
greet(); // Hallo Gast
greet("Anna"); // Hallo Anna
Klausur-Klassiker: gegeben Java-Code mit überladenen Methoden, entscheide welche Variante bei welchem Aufruf greift.
Side-Effects: was eine Funktion "nebenher" tut
Ein Side-Effect im engeren Sinn ist jede externe Wirkung einer Funktion: etwas in die Konsole drucken, eine Datei schreiben, einen Netzwerk-Call machen, eine globale Variable oder ein übergebenes Objekt mutieren. Daneben gibt es noch Abhängigkeiten von externem oder nicht-deterministischem Zustand: das Datum/die Uhrzeit lesen, Zufallszahlen ziehen, globale Variablen lesen. Diese schreiben nichts nach außen, machen die Funktion aber trotzdem nicht-deterministisch und damit nicht rein.
Beispiele:
System.out.println("...")ist ein Side-Effect (schreibt in die Konsole).liste.add(x)ist ein Side-Effect am übergebenen Objekt.Math.random()liest internen Zufalls-State → nicht-deterministisch, dadurch nicht rein.LocalDateTime.now()liest externen Zeit-State → nicht-deterministisch.
Side-Effects sind nicht "böse", aber sie machen Funktionen schwerer zu testen und zu verstehen. Ein gutes Programm trennt rechnende Funktionen (ohne Side-Effects, ohne externe Abhängigkeiten) von Funktionen, die etwas tun (mit Side-Effects).
Pure Functions
Eine pure function (reine Funktion) erfüllt zwei Eigenschaften:
- Determinismus: gleicher Input ergibt immer gleichen Output.
- Keine Side-Effects: keine externen Wirkungen, keine Abhängigkeit von veränderlichem externem Zustand.
quadrat(5) liefert immer 25 und ändert nichts → pure. System.out.println("Hallo") liefert nichts (void) und ändert externen State (Konsole) → nicht pure. Pure Functions sind besonders einfach zu testen und können in geeigneten Fällen sicher memoisiert oder gecacht werden, weil gleiche Eingaben immer gleiche Ausgaben liefern. Klausur-Klassiker: gegeben eine Funktion, entscheide ob sie pure ist.
public static void begruessung(String name) {
System.out.println("Hallo " + name);
}
begruessung("Anna"); // gibt "Hallo Anna" ausdef begruessung(name):
print(f"Hallo {name}")
begruessung("Anna") # gibt "Hallo Anna" ausInteraktiv
Funktion als Black-Box
Stell dir eine Funktion wie eine Maschine vor: oben kommt etwas rein, unten kommt etwas raus. Was dazwischen passiert ist die Implementierung.
Wähle eine Beispiel-Funktion (z. B. quadrat(x), verdoppeln(x) oder berechneSumme(a, b)), ändere die Eingabe und klicke auf Aufrufen. Der Visualizer zeigt animiert Parameter-Kopie, Berechnung im Body und Rückgabewert als Datenfluss.
Interaktive Visualisierung
Zeigt Funktionsaufrufe, Parameterwerte und Return-Werte als Flussdiagramm.
Erkenntnis: Reine/deterministische Funktionen liefern bei gleicher Eingabe immer gleiche Ausgabe, das macht sie testbar und vorhersehbar. Viele praktische Funktionen haben aber Seiteneffekte (Konsole, Datei, Zufall, Zeit) oder lesen externen Zustand und sind deshalb nicht rein. Funktionen bleiben trotzdem das wichtigste Werkzeug, um große Programme strukturiert zu halten.
Code-Stepper: Schritt für Schritt durchspielen
Vier interaktive Demos zu den klassischen Klausur-Themen rund um Funktionen: Call-by-value bei primitiven Typen, Mutation eines Objekts (Referenz sichtbar nach außen), Neuzuweisung eines Parameters (NICHT sichtbar) und Early-Return mit Guard. Klicke auf Step oder Auto und beobachte den Call-Stack mit Parameter-Kopien.
1. Call-by-value (Primitive): x im Parameter ist eine Kopie
Interaktive Visualisierung
Interaktive Komponente: probiere sie im Topic-Player oben aus.
2. Call-by-value (Reference): Mutation des Objekts ist sichtbar
Bei Objekten kopiert Java auch nur einen Wert - aber dieser Wert ist ein Referenzwert (ein Verweis) auf das Objekt im Heap. Beide Variablen zeigen jetzt auf dasselbe Objekt. Eine Mutation (.add(...), .set(...)) ist deshalb von außen sichtbar.
Interaktive Visualisierung
Interaktive Komponente: probiere sie im Topic-Player oben aus.
3. Reassignment des Parameters ist NICHT sichtbar
Wenn man den Parameter selbst auf ein NEUES Objekt umbiegt, ändert man nur die lokale Referenz-Kopie. Die Variable im Aufrufer zeigt weiter auf das alte Objekt. Klassischer Klausur-Stolperer.
Interaktive Visualisierung
Interaktive Komponente: probiere sie im Topic-Player oben aus.
4. Early-Return mit Guard: mehrere return-Pfade
Eine Funktion kann mehrere return-Anweisungen haben. Sobald eines erreicht wird, endet die Funktion. Klassisches Muster: Guard-Clause prüft Vorbedingungen am Anfang und kehrt früh zurück, danach folgt der "Happy Path".
Interaktive Visualisierung
Interaktive Komponente: probiere sie im Topic-Player oben aus.
Quiz
Quiz: Funktionen
Sechs Fragen zu Methoden-Signatur, Parameter, Rückgabewerten und Java call-by-value mit Referenzwerten.
Klausurfragen mit Lösungen (6)
- F1.Welche der folgenden Aussagen über Funktionen / Methoden ist KORREKT?
Antwort: Eine Funktion kann mehrere return-Anweisungen haben
Erklärung: Eine Funktion kann mehrere return-Anweisungen haben (z. B. in if-else-Branches), sobald eines erreicht wird, endet die Funktion. Falsch: Funktionen ohne Rückgabe heißen `void` (Java) bzw. geben implizit `None` (Python) zurück. Funktionen können beliebig oft aufgerufen werden. Parameter sind LOKAL zur Funktion.
- F2.Was bedeutet void in einer Java-Methoden-Signatur?
Antwort: Die Methode gibt keinen Wert zurück
Erklärung: `void` heißt: kein Rückgabewert. Die Methode tut etwas (z. B. ausgeben) aber liefert nichts zum Aufrufer zurück. Du kannst trotzdem `return;` schreiben um die Methode vorzeitig zu beenden, aber NIE `return wert;`.
- F3.In Java werden primitive Datentypen (int, double, boolean) per call-by-value an Methoden übergeben.
Antwort: Wahr
Erklärung: Stimmt. **Java ist immer call-by-value**, auch bei Objekten. Bei primitiven Typen wird der Wert kopiert. Bei Objekten (Strings, Arrays, Listen) wird die **Referenz als Wert** kopiert: Mutationen am Objekt können sichtbar sein, aber eine Neuzuweisung des Parameters ändert nicht die Variable im Aufrufer.
Typ: Wahr/Falsch
- F4.Welche Ausgabe produziert dieser Code?
Antwort: 5 10
Erklärung: `a` bleibt 5 (call-by-value: x ist eine Kopie, Änderungen sind lokal). `b` bekommt den Rückgabewert 10. Ergebnis: '5 10'. Klausur-Klassiker um call-by-value zu testen.
- F5.Welche der folgenden gehören zur Java-Methodensignatur (im Sinne von Overloading)?
Richtige Antworten: Methodenname; Parameter-Typen (Reihenfolge zählt)
Erklärung: Per Java Language Specification (§8.4.2) gehören zur Signatur nur **Methodenname + Parameter-Typen in Reihenfolge** (Einsteiger-Sicht für Overloading; bei generischen Methoden gehören auch Typ-Parameter formal zur Signatur, aber das ist fortgeschrittener Stoff). Der Rückgabetyp ist Teil der Methodendeklaration/des Methodenkopfs, gehört aber NICHT zur Overloading-Signatur, deshalb dürfen sich zwei überladene Methoden nicht nur durch den Rückgabetyp unterscheiden. Variablen-Namen im Body und die Anzahl Zeilen sind irrelevant.
Typ: Multi-Select
- F6.Was ist eine 'reine Funktion' (pure function)?
Antwort: Eine Funktion ohne Side-Effects, gleiche Eingabe → gleiche Ausgabe
Erklärung: Pure Function: keine Side-Effects und keine Abhängigkeit von veränderlichem oder nicht-deterministischem externem Zustand; gleiche Eingaben führen immer zu gleicher Ausgabe. Beispiel: `int quadrat(int x) { return x * x; }` ist pure. `void log(String s) { System.out.println(s); }` ist NICHT pure (Side-Effect: Konsole). Globale **Konstanten** zu lesen ist ok (unveränderlich), aber `Math.random()` oder `LocalDateTime.now()` lesen veränderlichen/nicht-deterministischen State und machen die Funktion nicht-rein.
public static void greet(String name) {
System.out.println("Hallo " + name);
}public static int verdoppeln(int x) {
x = x * 2;
return x;
}
public static void main(String[] args) {
int a = 5;
int b = verdoppeln(a);
System.out.println(a + " " + b);
}