Hier sind die 12 häufigsten Fehler aus Übungen und Klassenarbeiten zu diesem Kapitel — vom Plus, das in JavaScript verkettet, über SQL-Bedingungen bis zum String, der in Rust schon verschoben wurde. Jede Karte zeigt ein kurzes Beispiel „falsch“ und „richtig“ und erklärt, warum es so ist. Wer einen Fehler kennt, macht ihn seltener.
Die 12 häufigsten Fehler
1JavaScript: "5" + 3 ergibt 8
let punkte = "5"; // aus einem Eingabefeld console.log(punkte + 3); // 53
let punkte = Number("5"); console.log(punkte + 3); // 8
So steht es oft da: Man erwartet 8, weil „5 plus 3“ im Kopf eine Rechnung ist.
Richtig ist: JavaScript gibt 53 aus. Warum: Ist einer der beiden Werte ein Text, verkettet + — die 3 wird zu „3“ und angehängt. Nur -, * und / wandeln Text in Zahlen um ("5" * 3 = 15). Abhilfe: vorher mit Number(...) umwandeln.
Plus mit Text klebt zusammen — erst umwandeln, dann rechnen.
2PHP: mit + verketten
$name = "Ali"; echo "Hallo " + $name;
$name = "Ali"; echo "Hallo " . $name; echo "Hallo $name";
So steht es oft da: Aus JavaScript oder Java gewohnt: "Hallo " + $name.
Richtig ist: In PHP verkettet der Punkt: "Hallo " . $name. Warum: In PHP rechnet + immer mit Zahlen. "5" + 3 ergibt deshalb 8; bei Texten, die keine Zahlen sind, bricht PHP 8 mit einem TypeError ab. In doppelten Anführungszeichen setzt PHP Variablen direkt ein: "Hallo $name".
PHP: Punkt verkettet, Plus rechnet.
37 / 2 ist überall 3,5
// Java int a = 7; int b = 2; double h = a / b; // 3.0
// Java int a = 7; int b = 2; double h = a / 2.0; // 3.5
So steht es oft da: Man erwartet 3,5, weil h eine Kommazahl-Variable ist.
Richtig ist: Java rechnet zuerst 7 / 2 mit zwei int-Werten — das ist eine Ganzzahldivision: 3. Erst danach wird 3 als 3.0 gespeichert. Warum: Welcher Typ links steht, spielt für die Rechnung rechts keine Rolle. Genauso in C#, Go und Rust. Python (7 / 2 = 3.5, 7 // 2 = 3), JavaScript und PHP liefern 3,5.
int durch int bleibt int — in Java, C#, Go und Rust.
4Statisch typisiert heißt: Typ hinschreiben
// „Go ist dynamisch typisiert, // denn da steht kein Typ.“ n := 5 n = "fünf"
// n hat den festen Typ int n := 5 n = 7 // erlaubt: wieder int
So steht es oft da: Wo kein Typ im Quelltext steht, wird die Sprache für dynamisch gehalten.
Richtig ist: n := 5 legt eine Variable vom Typ int an — der Compiler leitet den Typ aus dem Wert ab (Typinferenz). n = "fünf" ist danach ein Compilerfehler. Warum: Statisch heißt, dass der Typ vor dem Lauf feststeht, nicht, dass man ihn aufschreiben muss. Dasselbe gilt für var in Java und C# und für let in Rust.
Statisch = Typ steht vor dem Lauf fest — ob hingeschrieben oder abgeleitet.
5SQL: Text ohne Anführungszeichen
SELECT titel FROM filme WHERE genre = Komoedie;
SELECT titel FROM filme WHERE genre = 'Komoedie';
So steht es oft da: Das Wort wird einfach so hingeschrieben wie in der Tabelle.
Richtig ist: Texte stehen in SQL in einfachen Anführungszeichen: genre = 'Komoedie'. Warum: Ohne Anführungszeichen sucht die Datenbank eine Spalte namens Komoedie und meldet einen Fehler. Zahlen wie jahr > 2010 brauchen keine Anführungszeichen.
Text in SQL: immer in einfache Anführungszeichen.
6SQL: AND statt OR
-- Filme aus 2019 und aus 2020 SELECT titel FROM filme WHERE jahr = 2019 AND jahr = 2020;
SELECT titel FROM filme WHERE jahr = 2019 OR jahr = 2020;
So steht es oft da: Die Aufgabe sagt „Filme aus 2019 und 2020“, also wird AND geschrieben.
Richtig ist: Kein Film kann gleichzeitig aus 2019 und aus 2020 sein — die Ergebnistabelle ist leer. Richtig ist OR. Warum: Die Bedingung wird für jede einzelne Zeile geprüft. AND: beide Teilbedingungen müssen für diese Zeile gelten; OR: eine reicht.
Frag pro Zeile: Muss beides gelten (AND) oder reicht eines (OR)?
7Rust: Variable nach dem Verschieben benutzt
let a = String::from("Hallo"); let b = a; println!("{}", a); // Fehler
let a = String::from("Hallo"); let b = &a; // nur leihen println!("{} {}", a, b);
So steht es oft da: Wie in Python: Nach b = a zeigen einfach beide auf „Hallo“.
Richtig ist: In Rust verschiebt let b = a; den Besitz des Strings (move). Danach ist a ungültig, und der Borrow Checker lehnt das Programm schon beim Kompilieren ab. Warum: Jeder Wert hat genau einen Besitzer — so weiß Rust ohne Garbage Collector, wann der Speicher freigegeben wird. Mit &a leihst du den Wert nur. (Zahlen wie i32 werden dagegen kopiert.)
Rust: Ein String hat genau einen Besitzer. Leihen mit &.
8Go: unbenutzte Variable
func main() { summe := 10 rest := summe % 3 fmt.Println(summe) }
func main() { summe := 10 rest := summe % 3 fmt.Println(summe, rest) }
So steht es oft da: Eine Variable, die man (noch) nicht braucht, schadet doch nicht.
Richtig ist: Der Go-Compiler meldet „declared and not used“ und übersetzt das Programm gar nicht. Warum: Go ist bewusst streng und einfach gehalten; unbenutzte Variablen sind oft ein Zeichen für einen Denkfehler. Entweder die Variable benutzen oder die Zeile löschen.
Go: Jede angelegte Variable muss auch benutzt werden.
9„Es läuft, also ist es fehlerfrei“
eingabe = input("Note? ") if eingabe == "1": print("Super! " + 1) else: print("Weiter so!")
eingabe = input("Note? ") if eingabe == "1": print("Super! " + str(1)) else: print("Weiter so!")
So steht es oft da: Das Python-Programm wurde mit „2“ und „3“ getestet und lief — also ist es fertig.
Richtig ist: Zeile 3 enthält einen Typfehler ("Super! " + 1). Der Interpreter bemerkt ihn erst, wenn er diese Zeile erreicht — also nur bei der Eingabe „1“. Warum: Ein Interpreter übersetzt und prüft Anweisung für Anweisung während des Laufs; Python ist zudem dynamisch typisiert. Ein Compiler einer statisch typisierten Sprache hätte einen solchen Typfehler vor dem Start gemeldet. Deshalb: jeden Zweig mindestens einmal testen.
Beim Interpreter zeigt sich ein Fehler erst, wenn seine Zeile läuft — teste jeden Zweig.
10PHP-Code ist im Browser sichtbar
<!-- „Seitenquelltext anzeigen“ zeigt: --> <?php echo "<p>Heute: " . date("d.m.") . "</p>"; ?>
<!-- „Seitenquelltext anzeigen“ zeigt: -->
<p>Heute: 25.09.</p>So steht es oft da: Im Browser kann man mit „Seitenquelltext anzeigen“ den PHP-Code einer Seite lesen.
Richtig ist: Der Browser bekommt nur das HTML, das der Server erzeugt hat. Warum: PHP läuft serverseitig: Der Server führt das Skript bei jeder Anfrage aus und schickt das Ergebnis. Deshalb darf z. B. ein Datenbank-Passwort im PHP-Code stehen, aber nie im JavaScript-Code, denn JavaScript wird an den Browser geschickt und läuft dort (clientseitig).
PHP bleibt auf dem Server, JavaScript reist zum Browser.
11Unity: Bewegung ohne Time.deltaTime
void Update() { transform.Translate(0.1f, 0, 0); }
void Update() { transform.Translate(3f * Time.deltaTime, 0, 0); }
So steht es oft da: Die Bewegung wird als fester Wert pro Aufruf von Update() angegeben.
Richtig ist: Update() läuft einmal pro Frame. Links bewegt sich das Objekt bei 30 fps um 3 Einheiten pro Sekunde, bei 144 fps um 14,4. Rechts ist der Weg immer 3 Einheiten pro Sekunde. Warum: Time.deltaTime ist die Zeit seit dem letzten Frame; Tempo · deltaTime ergibt den Weg für genau diesen Frame.
Pro Frame bewegen heißt: Tempo mal Time.deltaTime.
12Java und JavaScript verwechselt
// „Java und JavaScript sind // dieselbe Sprache.“ let zahl = 5; // in Java?
// Java int zahl = 5; // JavaScript let zahl = 5;
So steht es oft da: Weil beide 1995 erschienen sind und fast gleich heißen, gelten sie als eine Sprache.
Richtig ist: Java ist statisch typisiert, wird in Bytecode übersetzt und läuft in der JVM; die Verwandtschaftslinie ist C → C++ → Java → C#. JavaScript ist dynamisch typisiert, wird interpretiert bzw. im Browser per JIT übersetzt und ist die Sprache der Webseiten. Warum der ähnliche Name? Er war 1995 vor allem Werbung, weil Java gerade bekannt war.
Java ≠ JavaScript: andere Typen, anderer Übersetzungsweg, anderes Einsatzgebiet.
