• Keine Ergebnisse gefunden

Kontrollstrukturen Schleifen

Im Dokument Einführung in Java (Seite 32-40)

Aufgabe 2.3 class Point {

2.3 Kontrollstrukturen Schleifen

while (boolean expression) { statement(s)

}

Die Bedingung (boolean expression) wird am Schleifenanfang geprüft. Die Anweisungen in der Schleife werden gegebenenfalls nicht ein einziges Mal ausgeführt.

do {

statement(s)

} while (boolrean expression);

Die Bedingung (boolean expression) wird am Schleifenende geprüft. Die Anweisungen in der Schleife werden immer mindestens ein Mal ausgeführt.

for (initialization; boolean expression; increment) { statement(s)

}

Die Bedingung (boolean expression) wird am Schleifenanfang geprüft Die Anweisungen in der Schleife werden gegebenenfalls nicht ein einziges Mal ausgeführt.

Bedingte Ausführung und Alternativen if (boolean expression) { statement(s)

}

Die Anweisungen (statement(s)) werden nur ausgeführt, wenn die Bedingung wahr ist.

if (boolean expression) { statement(s) 1

} else {

statement(s) 2 }

Abhängig von der Bedingung werden alternativ nur die ersten Anweisungen (statement(s) 1) oder die zweiten Anweisungen (statement(s) 2) ausgeführt.

if (boolean expression 1) { statement(s) 1

} else if (boolean expression 2) { statement(s) 2

} else if (boolean expression 3) { statement(s) 3

} else {

statement(s) 4 }

Abhängig von den Bedingungen (logical expression 1 to 3) werden alternativ nur die ersten Anweisungen (statement(s) 1), oder die zweiten Anweisungen (statement(s) 2), usw. aus-geführt.

switch (integer expression) { case integer expression 1:

statement(s) 1 break;

case integer expression 2:

statement(s) 2 break;

...

...

default:

statement(s) break;

}

Abhängig vom ganzzahligen Ausdruck (integer expression) wird zum zugehörigen Fall (case) verzweigt. Die Anweisungen werden ab dieser Stelle bis zum "break" ausgeführt. Wenn keiner der Fälle zutrifft, wird der default-Zweig gewählt.

Weitere Kontrollanweisungen continue

Die Anweisungen unterbricht die innerste Schleife und führt dazu, dass deren Schleifen-bedingung erneut ausgewertet wird.

break

Die Anweisung beendet die innerste "switch", "for", "while" oder "do while" Anweisung.

2.4 Operatoren

Arithmetische Operatoren

Operator Use Description

+ op1 + op2 Adds op1 and op2 - op1 - op2 Subtracts op2 from op1

* op1 * op2 Multiplies op1 by op2 / op1 / op2 Divides op1 by op2

% op1 % op2 Computes the remainder of dividing op1 by op2

Operator Use Description

++ op++ Increments op by 1; evaluates the value of op before the increment operation

++ ++op Increments op by 1; evaluates the value of op after

the increment operation

-- op-- Decrements op by 1; evaluates the value of op before the increment operation

-- --op Decrements op by 1; evaluates the value of op after the increment operation

Vergleichsoperatoren

Operator Use Returns true if

> op1 > op2 op1 is greater than op2

>= op1 >= op2 op1 is greater than or equal to op2

< op1 < op2 op1 is less than op2

<= op1 <= op2 op1 is less than or equal to op2

== op1 == op2 op1 and op2 are equal

!= op1 != op2 op1 and op2 are not equal

Logische Operatoren

Operator Use Returns true if

&& op1 && op2 op1 and op2 are both true

|| op1 || op2 either op1 or op2 is true

! !op op is false

Schiebeoperatoren

Operator Use Operation

>> op1 >> op2 shift bits of op1 right by distance op2

<< op1 << op2 shift bits of op1 left by distance op2

>>> op1 >>> op2 shift bits of op1 right by distance op2 (unsigned)

Aufgabe 2.4

public class Shift {

public static void main(String[] args) { int val = 0xFFFFFFFF;

String hexStr1 = "0x" + Integer.toHexString(val >> 3);

String hexStr2 = "0x" + Integer.toHexString(val >>> 3);

System.out.println("val >> 3: " + hexStr1);

System.out.println("val >>> 3: " + hexStr2);

} }

Was gibt das Programm aus?

Bitoperatoren

Operator Use Operation

& op1 & op2 bitwise AND

| op1 | op2 bitwise OR

^ op1 ^ op2 bitwise XOR

~ ~op2 bitwise NOT

Zuweisungsoperatoren

Operator Use Equivalent to

= op1 = op2

+= op1 += op2 op1 = op1 + op2 -= op1 -= op2 op1 = op1 - op2

*= op1 *= op2 op1 = op1 * op2 /= op1 /= op2 op1 = op1 / op2

%= op1 %= op2 op1 = op1 % op2

&= op1 &= op2 op1 = op1 & op2

|= op1 |= op2 op1 = op1 | op2

^= op1 ^= op2 op1 = op1 ^ op2

<<= op1 <<= op2 op1 = op1 << op2

>>= op1 >>= op2 op1 = op1 >> op2

>>>= op1 >>>= op2 op1 = op1 >>> op2

Weitere Operatoren

Operator Use Description

?: op1 ? op2 : op3 If op1 is true, returns op2. Otherwise, returns op3.

[] type [] Declares an array of unknown length, which contains type elements.

[] type[op1] Creates and array with op1 elements. Must be used with the new operator.

[] op1[op2] Accesses the element at op2 index within the array op1. Indices begin at 0 and extend through the length of the array minus one.

. op1.op2 Is a reference to the op2 member of op1.

() op1(params) Declares or calls the method named op1 with the specified parameters.

(type) (type) op1 Casts (converts) op1 to type. An exception will be thrown if the type of op1 is

incompatible with type.

new new op1 Creates a new object or array. op1 is either a call to a constructor, or an array specification.

instanceof op1 instanceof op2 Returns true if op1 is an instance of op2.

Priorität der Operatoren

In der folgenden Tabelle sind die Operatoren in der Reihenfolge ihrer Priorität aufgelistet: je höher in der Tabelle ein Operator aufgeführt ist, desto größer ist seine Priorität. Operatoren in derselben Zeile haben die gleiche Priorität.

postfix operators [] . (params) expr++ expr-- unary operators ++expr --expr +expr -expr ~ ! creation or cast new (type)expr

multiplicative * / %

additive + -

shift << >> >>>

relational < > <= >= instanceof

equality == !=

bitwise AND &

bitwise exclusive OR ^ bitwise inclusive OR | logical AND &&

logical OR ||

conditional ? :

assignment = += -= *= /= %= &= ^= |= <<= >>= >>>=

Für Operatoren mit derselben Priorität gelten die folgenden Zusatzregeln:

− Wenn binäre Operatoren derselben Priorität mit Ausnahme von Zuweisungsoperatoren in einem Ausdruck (expression) zu finden sind, wird der Ausdruck von links nach rechts ausgewertet.

− Zuweisungsoperatoren werden von rechts nach links ausgewertet.

2.5 Ausnahmebehandlung (Exception-Handling)

Im Beispiel "Exception1" wird die Programmausführung mit einer Fehlermeldung beendet, wenn es zu einer Division durch Null kommt.

Beispiel, Exception1

public class Exception1 {

public static void main(String[] args) { for(int i = -2; i <= 2; i++)

System.out.println("100/" + i + " = " + 100/i);

} }

Auf der Konsole 100/-2 = -50 100/-1 = -100

Exception in thread "main" java.lang.ArithmeticException: / by zero at Exception1.main(Exception1.java:5)

In Java gibt es die Möglichkeit, einen Programmabschnitt zu markieren ("try", versuchen), in diesem Programmabschnitt auftretende Laufzeitfehler "abzufangen" ("catch") und auf sie dann geeignet zu reagieren.

Beispiel, Exception2

public class Exception2 {

public static void main(String[] args) { for(int i = -2; i <= 2; i++) {

try {

System.out.println("100/" + i + " = " + 100/i);

}

catch(ArithmeticException e) {

System.out.println("100/0 = ???? " + e);

} } } }

Auf der Konsole 100/-2 = -50 100/-1 = -100

100/0 = ???? java.lang.ArithmeticException: / by zero 100/1 = 100

100/2 = 50

Wenn es im try-Block zu einer Ausnahmesituation kommt, unterbricht die Laufzeitumgebung die normale Programmausführung. Das Programm wird dann mit den Anweisungen in der catch-Klausel fortgesetzt, die zur jeweiligen Ausnahmesituation passt, im Beispiel also in der catch-Klausel für eine arithmetische Ausnahmesituation (ArithmeticException). Gibt es keine passende catch-Klausel, wird die Fehlerbehandlung von der Laufzeitumgebung übernommen.

Java-Programme haben grundsätzlich die Pflicht, den Compiler über möglicherweise auf-tretende Fehler zu informieren. Dabei gilt die sogenannte "catch-or-throw"-Regel. Diese Regel besagt, dass jede Ausnahme entweder mit einer catch-Klausel abgefangen oder mit

"throws" weitergegeben werden muss. Das folgende Beispiel zeigt die Vorgehensweise bei der Weitergabe.

Beispiel, Exception3

public class Exception3 {

public static void main(String[] args) throws ArithmeticException { for(int i = -2; i <= 2; i++)

System.out.println("100/" + i + " = " + 100/i);

} }

Auf der Konsole 100/-2 = -50 100/-1 = -100

Exception in thread "main" java.lang.ArithmeticException: / by zero at Exception3.main(Exception3.java:5)

Um den Aufwand durch die Fehlerbehandlung nicht zu groß werden zu lassen, ist es für viele Laufzeitfehler zulässig, auf die explizite Weitergabe mit "throws" zu verzichten. Das Beispiel

"Exception1" zeigt, dass arithmetische Ausnahmesituationen zu diesen Laufzeitfehlern gehören.

Treten in dem eigenen Programm Fehler auf, die in dem von Java zu Verfügung gestellten Klassenbaum der Exceptions noch nicht vertreten sind, so muß man eine spezielle, eigene Ausnahmeklasse vereinbaren. Da Exceptions nichts anderes als Klassen sind, leitet man sich für seine Bedürfnisse einfach eine Klasse von der Klasse Exception oder einer Subklasse ab. Dadurch können die Exceptions unterschieden und entsprechend angepasste Fehlermeldungen ausgegeben werden. Das folgende Beispiel zeigt, wie man eine selbst definierte Exception generieren, auswerfen und wieder fangen kann.

Beispiel, Ausnahme1

class MyException extends Exception {

public MyException() {

// Aufruf des Konstruktors der Klasse Exception.

// Ihm wird ein String mit dem Fehlertext übergeben.

super ("Fehler ist aufgetreten!");

} }

public class MyClass {

public static void main (String[] args) {

// Dieser try-Block ist untypisch, da in ihm nur eine // Exception zu Demonstrationszwecken geworfen wird.

try {

MyException ex = new MyException();

throw ex;

// Anweisungen unterhalb einer throw-Anweisung in einem // try-Block werden nie abgearbeitet.

}

catch (MyException e) {

System.out.println (e.getMessage());

} } }

Auf der Konsole

Fehler ist aufgetreten!

Zur Erstellung einer eigenen Exception wird in dem Beispiel die Klasse MyException von der Klasse Exception abgeleitet. Im parameterlosen Konstruktor der Klasse MyException wird mit super() der Konstruktor der Klasse Exception aufgerufen. An den Konstruktor von Exception wird ein String übergeben, der den

Fehlertext enthält. Dieser Fehlertext kann dann im Fehlerfall mit der Methode getMessage() ausgelesen werden.

In obigem Beispiel wurde die Exception direkt im Hauptprogramm generiert und ausgeworfen mit dem Befehl

throw ex;

Die Exception kann aber auch von einer Methode erzeugt werden, die an irgendeiner Stelle im Hauptprogramm aufgerufen wird. Eine Exception, die eine Methode auslösen kann, muss dabei zwingend in der Deklaration der Methode mit Hilfe der throws-Klausel angegeben werden. Dadurch wird dem Aufrufer signalisiert, welche Ausnahmen von einer Methode ausgelöst bzw. weitergereicht werden. Der Aufrufer muss die geworfene Exception dann auffangen und sinnvoll behandeln. Im nachfolgenden Beispiel, das nur eine kleine Abwandlung gegennüber dem Beispiel "Ausnahme1" darstellt, wird dies verdeutlicht.

Beispiel, Ausnahme2

class MyException extends Exception {

public MyException() {

// Aufruf des Konstruktors der Klasse Exception.

// Ihm wird ein String mit dem Fehlertext übergeben.

super ("Fehler ist aufgetreten!");

} }

public class MyClass {

static void method() throws MyException {

MyException ex = new MyException();

throw ex;

}

public static void main (String[] args) {

// Dieser try-Block ist untypisch, da in ihm nur eine // Exception zu Demonstrationszwecken geworfen wird.

try {

method();

// Anweisungen unterhalb einer throw-Anweisung in einem // try-Block werden nie abgearbeitet.

}

catch (MyException e) {

System.out.println (e.getMessage());

} } }

2.6 Einfache Ein- und Ausgabe

Im Dokument Einführung in Java (Seite 32-40)