Thema in Kurzform:
Eine zentrale Notwendigkeit der Programmierung ist, dass ein Programm in Abhängigkeit von bestimmten Bedingungen einen unterschiedlichen Ablauf nehmen kann. Man spricht hier von Verzweigungen. Schauen wir uns das nun einmal genauer an.
// Schneller Code
if (preis <= 1000) {
System.out.println("gekauft!");
}
else{
System.out.println("zu teuer!");
}
Die einfachste Art der Verzweigung erhalten wir durch die if-Anweisung. Das Prinzip dahinter funktioniert nach der WENN-DANN-Logik:
Mit Ausdruck ist die zu prüfende Bedingung gemeint. Das Ergebnis dieser Prüfung ist immer entweder true oder false. Im Falle von true, wird ein entsprechender Codeblock ausgeführt. Konkret sieht das so aus:
boolean regen = true;
if (regen == true) {
System.out.println("Nimm Regenschirm!");
}
Unmittelbar nach dem Schlüsselwort if steht in den runden Klammern der zu prüfende Ausdruck. Da dieser in unserem Fall true ist, wird der Code innerhalb der geschweiften Klammern ausgeführt (System.out.println("Nimm Regenschirm!");). Andernfalls wäre dieser Code nicht ausgeführt worden.
Natürlich können Sie mehrere einzelne if-Prüfungen hintereinanderschreiben. Die Prüfungen erfolgen dann der Reihe nach unabhängig voneinander.
Stellen Sie sich ein Computerprogramm ruhig als einen Fluss mit Anfang und Ende vor. Wie in jedem Fluss, so gibt es auch in Computerprogrammen unterschiedliche Wege, auf dem der "Programmfluss" fließen kann. Welcher Weg das ist, hängt eben vom Ergebnis der Prüfung ab, die an der Verzweigung durchgeführt wird. Der Programmfluss des Codes oben lässt sich in einem Aktivitätsdiagramm so darstellen:
Solche Aktivitätsdiagramme helfen uns, den Ablauf eines Programms zu visualisieren und ihn besser nachvollziehen zu können. Machen Sie davon Gebrauch!
int preis = 3000;
int konto = 2000;
if (preis <= konto) {
System.out.println("Gekauft!");
}
In diesem Beispiel vergleichen wir zwei numerische Werte mithilfe eines Vergleichsoperators. Die Prüfung des Ausdrucks (preis <= konto) liefert den Wert false (3000 ist nicht kleiner oder gleich 2000). Der dazugehörige Codeblock in den geschweiften Klammern wird deshalb nicht ausgeführt.
Möchte man mehrere Bedingungen in einem Ausdruck prüfen, können wir dies mithilfe der logischen Operatoren erledigen. Ein Beispiel klärt die Lage:
int number = 50;
char sign = 'A';
if (number == 50 && sign =='A' ) {
System.out.println("Prüfung ergibt true!");
}
Da sowohl die Bedinung number == 50 als auch die Bedinung sign == 'A' true ergeben, ist der Ausdruck insgesamt true. Der Code innerhalb der geschweiften Klammern wird also ausgeführt.
Um Strings auf Gleichheit zu testen, müssen wir die Methode equals() verwenden. Der Grund hierfür ist, dass es sich bei Strings nicht um einen primitiven Datentyp, sondern um einen Objekttyp handelt und der Operator == auf Objekt-Identität testet). Sehen wir uns das einmal an:
String nachtwache = "Jon Schnee";
if (nachtwache.equals("Khal Drogo") ) {
System.out.println(" Die Nacht zieht auf und meine Wacht beginnt.");
}
Die if-Prüfung in Zeile 3 ruft auf dem String-Objekt die Methode equals auf und übergibt ihr als Argument das String-Literal Khal Drogo. Es wird nun geprüft, ob Khal Drogo dem String aus nachtwache gleicht. Nur dann, wenn es sich um denselben String handelt, ist der Ausdruck true und es wird der Text auf der Konsole ausgegeben. In unserem Fall ist der Ausdruck aber false, und somit wird der Code nicht ausgeführt.
Wir haben oben gesehen, dass ein bestimmter Code-Block ausgeführt wird, wenn der zu prüfende Ausdruck in den runden Klammern true ist. Ist der Ausdruck dagegen false, geschieht nichts.
Allerdings: Wenn der zu prüfende Ausdruck false ist, dann geschieht bei einer einfachen if-Verzweigung garnichts. Oft aber brauchen wir einen alternativen Code-Block, der eben dann ausgeführt werden soll, wenn die Prüfung false ergibt.
Was wir hierzu brauchen, ist eine if/else-Konstrollstruktur. Diese lässt sich logisch so beschreiben:
Hier ein Beispiel:
byte alter = 35;
if(alter >= 18){
System.out.println("Zutritt gewährt!");
}
else{
System.out.println("Zutritt verweigert!");
}
Wie wir sehen, wird der Text "Zutritt gewährt" auf der Konsole ausgegeben, da der Wert der Variable alter mit 35 größer/ gleich 18 ist. Andernfalls würde der else-Block ausgeführt werden und "Zutritt verweigert" geprinted.
Das Aktivitätsdiagramm mit unserer if-else-Kontrollstruktur sieht dann so aus:
Verzweigungsstrukturen können auch ineinander verschachtelt sein. Wir greifen das Beispiel von oben (Altersprüfung) auf und bauen eine simple Verschachtelung ein:
byte alter = 35;
if(alter >= 18){
System.out.println("Zutritt gewährt!");
boolean vip = false;
if(vip){
// Spezielle Angebote
}
else{
// Das normale Angebot
}
}
else{
System.out.println("Zutritt verweigert!");
}
Innerhalb des if-Blocks wird zunächst ein Text geprinted und eine boolesche Variable vip definiert. Danach öffnet sich eine neue Verschachtelungsstruktur, die prüft, ob die Variable vip auf true oder false. Je nach Ergebnis wird entweder der if-Block oder alternativ der else-Block ausgeführt.
Das passende Aktivitätsdiagramm sieht so aus:
Verschachtelungen sind in der Praxis oftmals notwendig, machen das Programm aber auch schwerer zu lesen. Vermeiden Sie daher zu komplizierte Verschachtelungskonstruktionen.
Eine Verzweigung in zwei Richtungen ist schön und gut. Es gibt aber oftmals Situationen, wo das nicht genügt, weil wir mehr als zwei Alternativen brauchen.
Für solche Fälle können wir in Java mit der Mehrfachverzweigung arbeiten. Alles, was wir dazu benötigen, ist das Schlüsselwort-Paar else if. Dieses setzen wir nach dem ersten if-Block ein. Wir setzen else if mit dazugehörigen Code-Block so oft mehrfach ein, wie wir Code-Alternativen brauchen:
int akku = 48;
if(akku < 25){
System.out.println("ROT - niedrige Akkuladung");
}
else if(akku < 50){
System.out.println("GELB - mittlere Akkuladung");
}
else if(akku < 100){
System.out.println("GRÜN - gute Akkuladung");
}
else{
System.out.println("100% Akku-Ladung");
}
Es gibt nun insgesamt vier Möglichkeiten, wie der Code "fließen" kann. Genau wie beim "normalen" if am Anfang, so wird bei jedem else if ein Ausdruck in Klammern geprüft. Ergibt die Prüfung true, wird der dazugehörende Code innerhalb der geschweiften Klammern { } ausgeführt.
Da in unserem Beispiel die Variable akku den Wert von 48 speichert, ergibt die die Prüfung akku < 50 true. Somit wird der dritte Codeblock unserer Kontrollstruktur ausgeführt.
Die gesamte Kontrollstruktur wird übrigens sofort beendet, sobald eine der Prüfungen erstmals true ist. Das heißt: Wie in einer "normalen" if/else-Verzweigung gibt es auch in einer else if-Konstruktion immer nur einen Weg, den der Programmfluss gehen kann. Sobald eine Prüfung erstmals true ist, gibt es für die folgenden Codeblöcke keine Chance mehr, da es garnicht mehr zu einer weiteren Prüfung kommt.
Das "normale" else muss ganz am Ende stehen, ist aber optional.
Sehen wir uns noch das Aktivitätsdiagramm dazu an:
Der ternäre Operator erleichtert uns die Arbeit mit einfachen Verzweigungsstrukturen. Genauer gesagt können wir den Code einer if/else-Konstruktion deutlich abkürzen.
Anstatt folgendes schreiben zu müssen...
boolean wahrheit = true;
String name = null;
if(wahrheit){
name = "Aristoteles";
}
else{
name = "Pinocchio";
}
... können wir die if/else-Konstruktion mit einer einzigen Code-Zeile vereinfachen:
boolean name = wahrheit ? "Aristoteles" : "Pinocchio";
Ist die Bedingung true, wird der Variablen name der Wert "Aristoteles" zugewiesen, ansonsten "Pinochhio".
Ternär bedeutet aus drei Grundeinheiten bestehend und so verfügt der ternäre Operator ? : drei Operanden: Die Bedingung, den Anweisungsblock 1 (falls Bedingung true) und den Anweisungsblock 2 (falls Bedingung false). Die allgemeine Syntax sieht so aus:
Ist die Bedingung true, wird der Code zwischen ? und : ausgeführt. Ist sie dagegen false, wird der Code nach dem : ausgeführt.
Einfache Verzweigungen mit dem ternären Operator zu lösen, spart im Alltag viel nervige Schreibarbeit. Auch wenn es am Anfang etwas gewöhnungsbedürftig ist.
Java Basics
[Java einrichten] [Variablen] [Primitive Datentypen] [Operatoren] [if else] [switch-case] [Arrays] [Schleifen]
Objektorientierung
[Einstieg] [Variablen ] [Konstruktor] [Methoden] [Rekursion] [Statische Member] [Initializer] [Pass-by-value] [Objektsammlungen] [Objektinteraktion] [Objekte löschen]
Klassenbibliothek
[Allgemeines] [String ] [Math] [Wrapper] [Scanner] [java.util.Arrays] [Date-Time-API]
Vererbung
[Einstieg Vererbung] [Konstruktoren bei Vererbung ] [Der protected Zugriffsmodifikator] [Abstrakte Klassen und Methoden] [Polymorphie in Java] [Typumwandlung] [Die Klasse Object] [Die toString()-Methode] [Objekte vergleichen] [Was ist ein Interface?]