Quiz
Quiz: Wertebereich
byte b = 127;
b++;
System.out.println(b);
-128
In Java sind alle primitiven Typen vorzeichenbehaftet, d. h. der Datentyp byte
hat „nur“ einen Wertebereich von -128 bis 127. Darauf muss man beim Umgang mit primitiven Typen achten, da es keine vorzeichenlose Typen gibt und man daher z. B. den Wert 255 nicht mit einem byte
, sondern nur mit einem short
darstellen kann.
Quiz: Primitive Java Typen
int i = 1;
double d;
d = i / 2;
System.out.println(d);
d = (double) i / 2;
System.out.println(d);
d = i / 2.0;
System.out.println(d);
0.0
0.5
0.5
Bei einer arithmetischen Operation wird in Java der Typ des Ergebnisses von den Operanden festgelegt und nicht vom Typ der Variable, an den das Ergebnis zugewiesen wird. Dividiert man einen Integer durch einen Integer, so ist das Ergebnis wieder ein Integer. Erst wenn mindestens einer der Operanden vom Typ double ist, wird im Beispiel das Ergebnis vom Typ double
sein.
Quiz: Kontrollstrukturen
boolean b = false;
if (b = true) {
System.out.println("Oops");
}
Oops
Im Gegensatz zu anderen Programmiersprachen (z. B. C oder C++) verlangt Java, dass der Ausdruck in der if-Bedingung immer zu einem boolean
ausgewertet werden kann. D. h. man kann keinen Integer oder einen anderen Typ verwenden. Verwendet man allerdings eine boolean
Variable, sollte man dringend davon Abstand nehmen, noch einen Vergleich mit ==
durchzuführen. Vergisst man hier nämlich ein Gleichheitszeichen, wird aus dem vermeintlichen Vergleich eine Zuweisung. Da jede Zuweisung selbst wieder einen Rückgabewert hat, nämlich den des rechten Operanden, kann man so aus Versehen ein syntaktisch korrektes if-Statement schreiben, das aber immer dem Wert des boolean-Literals folgt, mit dem man eigentlich vergleichen wollte.
int x = 3;
switch (x) {
case 1:
System.out.print("1 ");
case 2:
System.out.print("2 ");
case 3:
System.out.print("3 ");
case 4:
System.out.print("4 ");
default:
System.out.print("Passt nicht");
}
3 4 Passt nicht
Bei Java fällt bei eine switch
-Statement der Kontrollfluss durch alle case-Statements, die auf das case
folgen, bei dem die Bedingung zutraf. Daher muss man immer explizit ein break;
hinter die case-Statements schreiben, wenn man dieses Verhalten nicht möchte – was fast immer der Fall ist.
Quiz: Arrays
int[] array = new int[5];
for (int i = 1; i < 6; i++) {
array[i] = i;
}
System.out.println("Juhu!");
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at pr2.Puzzles.main(Puzzles.java:70)
Array-Indices in Java beginnen bei 0 und laufen bis Länge des Arrays - 1. D. h. für ein Array der Länge n
ist der gültige Bereich der Indices 0...n-1
. Im Beispiel wird aber das Array von 1 bis 5 durchlaufen, obwohl bei einem Array der Größe 5 nur die Indices von 0 bis 4 erlaubt wären.
Die Java-Laufzeitumgebung erzeugt bei einer Überschreitung der gültigen Array-Indices einen Laufzeit-Fehler (runtime exception) vom Typ ArrayIndexOutOfBoundsException
.
Quiz: Logische Operatoren
String s = null;
if ((s != null) & (s.length() > 0)) {
System.out.println(s.charAt(0));
}
System.out.println(s);
Exception in thread "main" java.lang.NullPointerException
at pr2.Puzzles.main(Puzzles.java:78)
Es gibt in Java zwei Arten von logischen Operatoren, die normalen |
und &
und die sogenannten Kurzschlussoperatoren ||
und &&
. Bei den normalen Operatoren werden alle (Teil-)Ausdrücke ausgewertet und erst dann wird der logische Operator angewandt. Bei den Kurzschlussoperatoren wird die Auswertung streng von links nach rechts durchgeführt und sie wird abgebrochen, sobald der logische Wert des Gesamtausdrucks feststeht.
Die Verwendung der normalen Operatoren führt in dem Beispiel dazu, dass die null-Referenz dereferenziert wird, was zu einer NullPointerException führt. Hätte man im Beispiel satt &
den Kurzschlussoperator &&
verwendet, wäre das Programm korrekt gelaufen.
String s = null;
if ((s != null) && (s.length() > 0)) {
System.out.println(s.charAt(0));
}
System.out.println(s);
Quiz: Parameterübergabe
void swap(String a, String b) {
String temp = a;
a = b;
b = temp;
}
void testSwap() {
String a = "Hallo";
String b = "Welt";
swap(a, b);
System.out.println(a + " " + b);
}
Hallo Welt
In Java werden Parameter an Methoden immer als Wert übergeben und nie als Referenz. D. h. die übergebene Variable wird kopiert und in der gerufenen Methode liegt eine Kopie dieser Variable vor. Diese Semantik gilt ebenfalls für Objektreferenzen; hier wird die Referenzvariable, die auf das Objekt zeigt, kopiert. Das Objekt selbst wird aber nicht kopiert. Daher kann die gerufene Methode zwar das Objekt manipulieren (was im gegebenen Beispiel wegen der Unveränderbarkeit von String allerdings nicht klappt) nicht aber den Wert der Referenz in der rufenden Methode ändern.
Aus diesem Grund geht die swap()
-Methode im Beispiel komplett in die Leere und hat keinerlei Auswirkungen auf die rufende Methode testSwap()
.