Hier sind die 12 häufigsten Fehler aus dem ganzen Kapitel — vom fehlenden Semikolon bis zur Suche in der Liste. Jede Karte zeigt den fehlerhaften Code, die Meldung, die du dann wirklich bekommst, und den korrigierten Code. Lies die Meldungen genau: Wer sie einmal verstanden hat, findet den Fehler in Sekunden.
Die 12 häufigsten Fehler
1Semikolon am Zeilenende vergessen
public class Wecker {
public static void main(String[] args) {
System.out.println("Aufstehen!")
System.out.println("Noch 5 Minuten ...");
}
}
Wecker.java:3: error: ';' expected
System.out.println("Aufstehen!")
^
1 error
System.out.println("Aufstehen!");
System.out.println("Noch 5 Minuten ...");
So wird es oft gemacht: Aus Python gewohnt, endet die Zeile einfach mit dem Zeilenumbruch. In Java übersetzt javac dann gar nichts — es entsteht keine .class-Datei, das Programm startet nicht.
Richtig ist: Jede Anweisung endet mit ;. Nach Kopfzeilen mit { (Klasse, Methode, if, for) steht dagegen kein Semikolon.
Anweisung → Semikolon. Block-Kopf mit { → kein Semikolon.
2Ganzzahldivision übersehen — der Schnitt ist zu klein
int strecke = 23; // km
int tage = 4;
double schnitt = strecke / tage;
System.out.println(schnitt);
5.0
double schnitt = (double) strecke / tage; System.out.println(schnitt);
5.75
So wird es oft gemacht: „Das Ergebnis ist double, also kommen Nachkommastellen heraus.“ Aber 23 / 4 sind zwei int-Werte — Java rechnet ganzzahlig, schneidet ab und erhält 5. Erst danach wird daraus 5.0.
Richtig ist: Mindestens ein Operand muss double sein, z. B. mit (double) strecke / tage oder strecke / 4.0. Dann ist das Ergebnis 5,75 km pro Tag.
int / int ergibt immer int — egal, wohin das Ergebnis gespeichert wird.
3Kommazahl in einer int-Variablen gespeichert
int preis = 8.50; // Kinokarte
Kino.java:3: error: incompatible types: possible lossy conversion from double to int
int preis = 8.50;
^
1 error
double preis = 8.50;
So wird es oft gemacht: In Python bekommt eine Variable jeden Wert. In Java steht der Typ fest: In int passen nur ganze Zahlen. javac verweigert die Übersetzung, weil die 0,50 € verloren gingen.
Richtig ist: Für Kommazahlen double wählen. Umgekehrt klappt es automatisch: double d = 8; wird zu 8.0. Wer bewusst abschneiden will, schreibt (int) 8.50 und erhält 8.
Erst den Typ überlegen, dann die Variable anlegen — der Compiler prüft ihn vor dem Start.
4Texte mit == statt mit equals verglichen
Scanner sc = new Scanner(System.in);
String antwort = sc.nextLine(); // Eingabe: ja
System.out.println(antwort == "ja");
false
System.out.println(antwort.equals("ja"));
true
So wird es oft gemacht: In Python vergleicht == den Text. In Java prüft == bei Strings nur, ob beide Variablen auf dasselbe Objekt zeigen. Die Eingabe ist ein neues Objekt — das Ergebnis ist false, obwohl „ja“ eingetippt wurde.
Richtig ist: antwort.equals("ja") vergleicht Zeichen für Zeichen. == bleibt für int, double, char und boolean richtig.
Zahlen mit ==, Texte mit .equals(…).
5return fehlt — obwohl alle Fälle abgedeckt scheinen
public static String bewertung(int prozent) {
if (prozent >= 50) {
return "bestanden";
} else if (prozent < 50) {
return "nicht bestanden";
}
}
Test.java:8: error: missing return statement
}
^
1 error
public static String bewertung(int prozent) {
if (prozent >= 50) {
return "bestanden";
} else {
return "nicht bestanden";
}
}
So wird es oft gemacht: Du weißt: Eine Zahl ist entweder ≥ 50 oder < 50. Der Compiler rechnet das aber nicht nach. Für ihn gibt es einen Weg, auf dem die Methode ohne return endet — und eine Methode mit Rückgabetyp String muss auf jedem Weg etwas zurückgeben.
Richtig ist: Den letzten Fall mit else schreiben oder nach dem if noch ein return ergänzen.
Rückgabetyp ≠ void → jeder mögliche Weg durch die Methode endet mit return.
6Typen aus dem Klassendiagramm in Java übernommen
- - name: Zeichenkette
- - leben: Ganzzahl
- c Drache(name: Zeichenkette)
public class Drache {
private String name;
private Ganzzahl leben;
}
Drache.java:3: error: cannot find symbol
private Ganzzahl leben;
^
symbol: class Ganzzahl
location: class Drache
1 error
public class Drache {
private String name;
private int leben;
}
So wird es oft gemacht: Die Zeile - leben: Ganzzahl wird fast wörtlich abgeschrieben. Java kennt aber keinen Typ „Ganzzahl“ und sucht vergeblich nach einer Klasse mit diesem Namen.
Richtig ist: Übersetzen: Ganzzahl → int, Fließkommazahl → double, Wahrheitswert → boolean, Zeichen → char, Zeichenkette → String; - → private, + → public; der Typ wandert nach vorn.
- leben: Ganzzahl wird private int leben; — nie wörtlich abschreiben.
7Objekt ohne new erzeugt
Zug z = Zug("ICE", 8);
Main.java:3: error: cannot find symbol
Zug z = Zug("ICE", 8);
^
symbol: method Zug(String,int)
location: class Main
1 error
Zug z = new Zug("ICE", 8);
So wird es oft gemacht: In Python entsteht ein Objekt mit Zug("ICE", 8). In Java hält der Compiler das für den Aufruf einer Methode Zug(String,int), die es nicht gibt.
Richtig ist: new erzeugt das Objekt und ruft dabei den Konstruktor auf. Links steht der Typ der Variablen, hier ebenfalls Zug.
Neues Objekt = Typ name = new Klasse(werte);
8this fehlt — der Konstruktor speichert nichts
public Planet(String name, double masse) {
name = name;
masse = masse;
}
// new Planet("Mars", 0.64) → getName(), getMasse()
null 0.0
public Planet(String name, double masse) {
this.name = name;
this.masse = masse;
}
Mars 0.64
So wird es oft gemacht: Parameter und Attribut heißen gleich. In name = name; ist dann beide Male der Parameter gemeint — er wird sich selbst zugewiesen. Das Attribut bleibt bei null bzw. 0.0.
Richtig ist: this.name ist das Attribut dieses Objekts, name allein der Parameter. Also this.name = name;.
Gleicher Name bei Parameter und Attribut → links this. davor.
9Privates Attribut direkt von außen gesetzt
Thermostat t = new Thermostat(); // startet mit 20
t.temperatur = 50;
Main.java:4: error: temperatur has private access in Thermostat
t.temperatur = 50;
^
1 error
// in der Klasse Thermostat:
public void setTemperatur(int temperatur) {
if (temperatur >= 5 && temperatur <= 30) {
this.temperatur = temperatur;
}
}
// außerhalb:
t.setTemperatur(50); // wird abgewiesen, bleibt 20
So wird es oft gemacht: Aus einer anderen Klasse wird das Attribut direkt gesetzt. Weil es private ist, bricht javac ab. Wer daraufhin einfach public schreibt, erlaubt auch unsinnige Werte wie 50 °C im Wohnzimmer.
Richtig ist: Attribut privat lassen und einen Setter anbieten, der nur gültige Werte übernimmt. Ungültige Werte werden abgewiesen, nicht stillschweigend auf die Grenze gesetzt.
Attribute private, Zugriff nur über getX() und einen prüfenden setX(…).
10Schleife läuft bis length — einen Schritt zu weit
int[] tore = {2, 0, 3, 1, 4};
int summe = 0;
for (int i = 0; i <= tore.length; i++) {
summe = summe + tore[i];
}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
at Main.main(Main.java:6)
for (int i = 0; i < tore.length; i++) {
summe = summe + tore[i];
}
// summe = 10
So wird es oft gemacht: Das Array hat 5 Plätze, also soll die Schleife „bis 5“ laufen. Die Indizes gehen aber nur von 0 bis 4. Beim Zugriff auf tore[5] bricht die JVM mit einem Laufzeitfehler ab.
Richtig ist: i < tore.length. Der letzte gültige Index ist immer length − 1. Bei einer ArrayList gilt dasselbe mit size().
Indizes laufen von 0 bis length − 1 — in der Bedingung steht <, nicht <=.
11super(…) im Konstruktor der Unterklasse vergessen
public class Gitarre extends Instrument {
private int saiten;
public Gitarre(String name, int saiten) {
this.saiten = saiten;
}
}
// Instrument hat nur den Konstruktor Instrument(String name)
Gitarre.java:7: error: constructor Instrument in class Instrument cannot be applied to given types;
public Gitarre(String name, int saiten) {
^
required: String
found: no arguments
reason: actual and formal argument lists differ in length
1 error
public Gitarre(String name, int saiten) {
super(name);
this.saiten = saiten;
}
So wird es oft gemacht: Die Gitarre setzt nur ihr neues Attribut. Den geerbten Teil muss aber der Konstruktor der Oberklasse füllen. Fehlt super(…), ruft Java heimlich super() ohne Werte auf — und den gibt es hier nicht.
Richtig ist: Als erste Anweisung super(name);, danach die eigenen Attribute. An name kommt die Gitarre ohnehin nicht direkt heran, weil es in Instrument private ist.
Unterklassen-Konstruktor: zuerst super(…), dann this.neu = neu;
12Die Suche gibt nach dem ersten Vergleich auf
public Spieler suche(String name) {
for (Spieler s : kader) {
if (s.getName().equals(name)) {
return s;
} else {
return null;
}
}
return null;
}
// kader: Ben, Lina → suche("Lina").getName()
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Spieler.getName()" because the return value of "Team.suche(String)" is null
at Main.main(Main.java:7)
public Spieler suche(String name) {
for (Spieler s : kader) {
if (s.getName().equals(name)) {
return s;
}
}
return null; // erst NACH der Schleife: niemand gefunden
}
So wird es oft gemacht: „Wenn der Name nicht passt, gib null zurück.“ Dann wird nur der erste Spieler geprüft: Ben passt nicht, die Methode endet mit null, Lina wird nie angeschaut. Der Aufruf getName() an null führt zur NullPointerException.
Richtig ist: Im Schleifenrumpf nur bei einem Treffer return. Erst wenn alle Elemente geprüft sind, steht fest, dass niemand passt — also return null; nach der Schleife.
„Gefunden“ darf die Schleife beenden, „nicht gefunden“ erst ihr Ende.
