2. Grundlagen der Programmiersprache Java
2.1. Einführung
Wir behandeln Java zunächst als klassische Programmiersprache. Auf Objekte werden wir später eingehen.
In einem Programm gibt es zwei Arten von Elementen
- Daten
- Anweisungen, die diese bearbeiten
Man ist im Allgemeinen bestrebt, die Daten von den Anweisungen zu trennen:

2.2. Daten in Java
Java verwendet die folgenden Datentypen:
- Ganzzahlen
- Reelle Zahlen
- Zeichen und Zeichenfolgen
- Boolesche Werte
- Objekte
2.2.1. Vordefinierte Datentypen
Typ | Kodierung | Bereich |
char | 2 Byte | Unicode-Zeichen |
int | 4 Bytes | [-231, 231-1] |
long | 8 Bytes | [-263, 263 -1] |
byte | 1 Byte | [-27 , 27 -1] |
short | 2 Bytes | [-215, 215-1] |
float | 4 Bytes | [3.4 10-38, 3.4 10+38] als Absolutwert |
double | 8 Bytes | [1.7 10-308 , 1.7 10+308] als Absolutwert |
boolean | 1 Bit | wahr, falsch |
String | Objektreferenz | Zeichenkette |
Date | Objektreferenz | Datum |
Character | Objektreferenz | char |
Integer | Objektreferenz | int |
Long | Objektreferenz | long |
Byte | Objektreferenz | Byte |
Float | Objektreferenz | Float |
Double | Objektreferenz | double |
Boolean | Objektreferenz | bool |
2.2.2. Notation von Literalwerten
entier | 145, -7, 0xFF (hexadezimal) |
Double | 134,789, -45E-18 (-45 × 10⁻¹⁸) |
Float-Zahl | 134.789F, -45E-18F (-45 × 10⁻¹⁸) |
caractère | 'A', 'b' |
Zeichenkette | „heute“ |
booléen | true, false |
date | new Date(13,10,1954) (Tag, Monat, Jahr) |
2.2.3. Datenmeldung
2.2.3.1. Rolle der Deklarationen
Ein Programm verarbeitet Daten, die durch einen Namen und einen Typ gekennzeichnet sind. Diese Daten werden im Speicher abgelegt. Bei der Übersetzung des Programms weist der Compiler jedem Datenelement einen Speicherplatz zu, der durch eine Adresse und eine Größe gekennzeichnet ist. Dabei stützt er sich auf die vom Programmierer vorgenommenen Deklarationen.
Außerdem ermöglichen diese dem Compiler, Programmierfehler zu erkennen. So wird die Operation
x = x * 2;
wird beispielsweise als fehlerhaft deklariert, wenn x eine Zeichenkette ist.
2.2.3.2. Deklaration von Konstanten
Die Syntax zur Deklaration einer Konstante lautet wie folgt:
final Typ Name = Wert; //definiert die Konstante „Name“ = „Wert“
Beispiel: final float PI=3.141592F;
Hinweis
Warum Konstanten deklarieren?
- Das Programm lässt sich leichter lesen, wenn man der Konstante einen aussagekräftigen Namen gibt:
Beispiel: final float taux_tva = 0.186F;
- Die Änderung des Programms wird einfacher, falls sich die „Konstante“ ändern sollte. Wenn also im vorigen Fall der Mehrwertsteuersatz auf 33 % steigt, muss lediglich die Anweisung geändert werden, die ihren Wert definiert:
final float taux_tva=0.33F;
Hätte man im Programm explizit den Wert 0,186 verwendet, müssten zahlreiche Anweisungen geändert werden.
2.2.3.3. Deklaration von Variablen
Eine Variable wird durch einen Namen identifiziert und bezieht sich auf einen Datentyp. Der Name einer Java-Variablen besteht aus n Zeichen, wobei das erste ein Buchstabe sein muss und die übrigen Buchstaben oder Ziffern sein können. Java unterscheidet zwischen Groß- und Kleinschreibung. Daher sind die Variablen „FIN“ und „fin“ unterschiedlich.
Variablen können bei ihrer Deklaration initialisiert werden. Die Syntax zur Deklaration einer oder mehrerer Variablen lautet:
wobei identificateur_de_type ein vordefinierter Typ oder ein vom Programmierer definierter Objekttyp ist.
2.2.4. Konvertierungen zwischen Zahlen und Zeichenketten
Zahl -> Zeichenkette | "" + Zahl |
Zeichenkette -> int | Integer.parseInt(Zeichenkette) |
Zeichenkette -> long | Long.parseLong(Zeichenkette) |
Zeichenkette -> double | Double.valueOf(Zeichenkette).doubleValue() |
Zeichenkette -> Float | Float.valueOf(Zeichenkette).floatValue() |
Hier ist ein Programm, das die wichtigsten Techniken zur Konvertierung zwischen Zahlen und Zeichenfolgen vorstellt. Die Konvertierung einer Zeichenfolge in eine Zahl kann fehlschlagen, wenn die Zeichenfolge keine gültige Zahl darstellt. In diesem Fall wird ein schwerwiegender Fehler ausgelöst, der in Java als „Exception“ bezeichnet wird. Dieser Fehler kann durch die folgende Klausel try/catch behandelt werden:
try{
appel de la fonction susceptible de générer l'exception
} catch (Exception e){
traiter l'exception e
}
instruction suivante
Wenn die Funktion keine Ausnahme auslöst, wird zur nächsten Anweisung übergegangen; andernfalls wird der Hauptteil der Klausel catch aufgerufen und anschließend zur nächsten Anweisung übergegangen. Wir werden später noch auf die Ausnahmebehandlung zurückkommen.
import java.io.*;
public class conv1{
public static void main(String arg[]){
String S;
final int i=10;
final long l=100000;
final float f=(float)45.78;
double d=-14.98;
// Zahl --> Zeichenkette
S=""+i;
affiche(S);
S=""+l;
affiche(S);
S=""+f;
affiche(S);
S=""+d;
affiche(S);
//Boolescher Wert --> Zeichenfolge
final boolean b=false;
S=""+new Boolean(b);
affiche(S);
// Zeichenkette --> int
int i1;
i1=Integer.parseInt("10");
affiche(""+i1);
try{
i1=Integer.parseInt("10.67");
affiche(""+i1);
} catch (Exception e){
affiche("Erreur "+e);
}
// Zeichenkette --> long
long l1;
l1=Long.parseLong("100");
affiche(""+l1);
try{
l1=Long.parseLong("10.675");
affiche(""+l1);
} catch (Exception e){
affiche("Erreur "+e);
}
// Zeichenkette --> double
double d1;
d1=Double.valueOf("100.87").doubleValue();
affiche(""+d1);
try{
d1=Double.valueOf("abcd").doubleValue();
affiche(""+d1);
} catch (Exception e){
affiche("Erreur "+e);
}
// Zeichenkette --> Float
float f1;
f1=Float.valueOf("100.87").floatValue();
affiche(""+f1);
try{
d1=Float.valueOf("abcd").floatValue();
affiche(""+f1);
} catch (Exception e){
affiche("Erreur "+e);
}
}// Ende main
public static void affiche(String S){
System.out.println("S="+S);
}
}// Ende der Klasse
Die folgenden Ergebnisse wurden erzielt:
S=10
S=100000
S=45.78
S=-14.98
S=false
S=10
S=Erreur java.lang.NumberFormatException: 10.67
S=100
S=Erreur java.lang.NumberFormatException: 10.675
S=100.87
S=Erreur java.lang.NumberFormatException: abcd
S=100.87
S=Erreur java.lang.NumberFormatException: abcd
2.2.5. Datentabellen
Ein Java-Array ist ein Objekt, mit dem Daten desselben Typs unter einem gemeinsamen Bezeichner zusammengefasst werden können. Die Deklaration lautet wie folgt:
Typ Array[] = new Typ[n] oder Typ[] Array = new Typ[n]
Beide Syntaxen sind zulässig. n ist die Anzahl der Daten, die das Array enthalten kann. Die Syntax Array[i] bezeichnet das Datenelement Nr. i, wobei i zum Intervall [0,n-1] gehört. Jeder Verweis auf den Datenpunkt „Tableau[i]“, bei dem „i“ nicht zum Intervall „[0,n-1]“ gehört, löst eine Ausnahme aus.
Ein zweidimensionales Array kann wie folgt deklariert werden:
Typ Array[][] = new Typ[n][p] oder Typ[][] Array = new Typ[n][p]
Die Syntax „Tableau[i]“ bezeichnet den Datensatz Nr. i von Tableau, wobei i zum Intervall [0,n-1] gehört. „Tableau[i]“ ist selbst ein Array: „Tableau[i][j]“ bezeichnet den Datensatz Nr. j aus „Tableau[i]“, wobei j zum Intervall [0,p-1] gehört. Jeder Verweis auf einen Datensatz aus „Tableau“ mit falschen Indizes führt zu einem schwerwiegenden Fehler.
Hier ein Beispiel:
public class test1{
public static void main(String arg[]){
float[][] taux=new float[2][2];
taux[1][0]=0.24F;
taux[1][1]=0.33F;
System.out.println(taux[1].length);
System.out.println(taux[1][1]);
}
}
und die Ergebnisse der Ausführung:
Ein Array ist ein Objekt mit dem Attribut length: Dies ist die Größe des Arrays.
2.3. Die Grundanweisungen in Java
Man unterscheidet
- zwischen den vom Computer ausgeführten Grundbefehlen
- die Anweisungen zur Steuerung des Programmablaufs.
Die elementaren Befehle werden deutlich, wenn man die Struktur eines Mikrocomputers und seiner Peripheriegeräte betrachtet.

-
Einlesen von Informationen von der Tastatur
-
Verarbeitung von Informationen
-
Ausgabe von Informationen auf dem Bildschirm
-
Einlesen von Informationen aus einer Datei auf der Festplatte
-
Schreiben von Informationen in eine Datei auf der Festplatte
2.3.1. Ausgabe auf dem Bildschirm
Die Syntax des Befehls zum Schreiben auf den Bildschirm lautet wie folgt:
System.out.println(Ausdruck) oder System.err.println(Ausdruck)
wobei expression ein beliebiger Datentyp ist, der in eine Zeichenkette umgewandelt werden kann, um auf dem Bildschirm angezeigt zu werden. Im vorangegangenen Beispiel haben wir zwei Schreibanweisungen gesehen:
System.out schreibt in eine Textdatei, bei der es sich standardmäßig um den Bildschirm handelt. Das Gleiche gilt für System.err. Diese Dateien tragen die Nummern (bzw. descripteur) 1 bzw. 2. Der Eingabestrom von der Tastatur (System.in) wird ebenfalls als Textdatei mit dem Deskriptor 0 betrachtet. Sowohl DOS als auch Unix unterstützen die Befehlsverknüpfung (Pipe):
Alles, was commande1 mit System.out schreibt, wird an den Eingang System.in von commande2 weitergeleitet. Anders ausgedrückt: commande2 liest mit System.in die Daten, die von commande2 mit System.out erzeugt wurden und daher nicht mehr auf dem Bildschirm angezeigt werden. Dieses System wird unter Unix häufig verwendet. In dieser Pipe wird der Datenstrom von System.err hingegen nicht umgeleitet: Er schreibt auf den Bildschirm. Deshalb wird er zum Ausgeben von Fehlermeldungen verwendet (daher auch sein Name err): So ist sichergestellt, dass bei einer Befehlsweiterleitung die Fehlermeldungen weiterhin auf dem Bildschirm angezeigt werden. Man sollte sich daher angewöhnen, Fehlermeldungen mit dem Datenstrom System.err auf den Bildschirm zu schreiben, anstatt mit dem Datenstrom System.out.
2.3.2. Auslesen von über die Tastatur eingegebenen Daten
Der Datenstrom von der Tastatur wird durch das Objekt System.in vom Typ InputStream bezeichnet. Dieser Objekttyp ermöglicht das Einlesen von Daten Zeichen für Zeichen. Es ist Aufgabe des Programmierers, anschließend in diesem Zeichenstrom die für ihn relevanten Informationen zu finden. Der Typ InputStream ermöglicht es nicht, eine Textzeile auf einmal einzulesen. Der Typ BufferedReader ermöglicht dies mit der Methode readLine.
Um über die Tastatur eingegebene Textzeilen lesen zu können, wird aus dem Eingabestrom System.in vom Typ InputStream ein weiterer Eingabestrom erstellt, diesmal vom Typ BufferedReader:
Wir werden hier nicht auf die Details dieser Anweisung eingehen, die den Begriff der Objektkonstruktion beinhaltet. Wir werden sie so verwenden, wie sie ist.
Die Erstellung eines Streams kann fehlschlagen: In diesem Fall wird ein schwerwiegender Fehler, in Java als „Ausnahme“ bezeichnet, ausgelöst. Immer wenn eine Methode eine Ausnahme auslösen kann, verlangt der Java-Compiler, dass diese vom Programmierer abgefangen wird. Um den oben genannten Eingabestream zu erstellen, muss daher tatsächlich folgender Code geschrieben werden:
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
System.err.println("Erreur " +e);
System.exit(1);
}
Auch hier soll die Ausnahmebehandlung nicht näher erläutert werden. Sobald der vorherige Datenstrom IN aufgebaut ist, kann mit der Anweisung eine Textzeile gelesen werden:
Die über die Tastatur eingegebene Zeile wird in der Variablen ligne gespeichert und kann anschließend vom Programm weiterverarbeitet werden.
2.3.3. Beispiel für Ein- und Ausgabe
Hier ist ein Programm zur Veranschaulichung der Ein- und Ausgabeoperationen über Tastatur und Bildschirm:
import java.io.*; // erforderlich für die Verwendung von E/A-Streams
public class io1{
public static void main (String[] arg){
// Schreiben in den Stream System.out
Object obj=new Object();
System.out.println(""+obj);
System.out.println(obj.getClass().getName());
// Schreiben in den Datenstrom System.err
int i=10;
System.err.println("i="+i);
// Lesen einer über die Tastatur eingegebenen Zeile
String ligne;
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
affiche(e);
System.exit(1);
}
System.out.print("Tapez une ligne : ");
try{
ligne=IN.readLine();
System.out.println("ligne="+ligne);
} catch (Exception e){
affiche(e);
System.exit(2);
}
}//Ende der Eingabe
public static void affiche(Exception e){
System.err.println("Erreur : "+e);
}
}//Ende der Klasse
und die Ergebnisse der Ausführung:
C:\Serge\java\bases\iostream>java io1
java.lang.Object@1ee78b
java.lang.Object
i=10
Tapez une ligne : je suis là
ligne=je suis là
Die Anweisungen
sollen zeigen, dass jedes beliebige Objekt angezeigt werden kann. Wir werden hier nicht näher auf die Bedeutung der angezeigten Inhalte eingehen. Außerdem wird im folgenden Block der Wert eines Objekts angezeigt:
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
affiche(e);
System.exit(1);
}
Die Variable e ist ein Objekt vom Typ Exception, das hier mit dem Aufruf affiche(e) angezeigt wird. Wir sind dieser Anzeige des Werts einer Ausnahme bereits im oben gezeigten Konvertierungsprogramm begegnet, ohne darauf einzugehen.
2.3.4. Zuweisung des Werts eines Ausdrucks an eine Variable
Wir befassen uns hier mit der Operation variable=expression;
Der Ausdruck kann folgender Art sein: arithmetisch, relational, boolesch, Zeichen
2.3.4.1. Interpretation der Zuweisungsoperation
Die Operation variable=expression; ist selbst ein Ausdruck, dessen Auswertung wie folgt abläuft:
- Die rechte Seite der Zuweisung wird ausgewertet: Das Ergebnis ist ein Wert V.
- Der Wert V wird der Variablen zugewiesen
- Der Wert V ist zugleich der Wert der Zuweisung, die nun als Ausdruck betrachtet wird.
Daher ist die Operation V1=V2=Ausdruck zulässig ist. Aufgrund der Priorität wird der Operand „=“ ganz rechts ausgewertet. Wir erhalten also V1=(V2=Ausdruck). Der Ausdruck V2=Ausdruck wird ausgewertet und ergibt den Wert V. Die Auswertung dieses Ausdrucks führte dazu, dass V an V2 zugewiesen wurde. Der nächste Operator „=“ wird dann in der Form V1=V ausgewertet. Der Wert dieses Ausdrucks ist wiederum V. Seine Auswertung führt zur Zuweisung von V an V1. Somit ist die Operation V1=V2=Ausdruck ist ein Ausdruck, dessen Auswertung
1: die Zuweisung des Wertes von expression an die Variablen V1 und V2 bewirkt
2: den Wert von expression als Ergebnis liefert.
Man kann dies auf einen Ausdruck der folgenden Form verallgemeinern: V1 = V2 = ... = Vn = Ausdruck
2.3.4.2. Arithmetischer Ausdruck
Die Operatoren für arithmetische Ausdrücke sind folgende:
+: Addition
- : Subtraktion
*: Multiplikation
/: Division: Das Ergebnis ist der exakte Quotient, wenn mindestens einer der Operanden reell ist. Sind beide Operanden ganzzahlig, ist das Ergebnis der ganzzahlige Quotient. Somit ergibt 5/2 -> 2 und 5,0/2 -> 2,5.
% : Division: Das Ergebnis ist der Rest, unabhängig von der Art der Operanden, wobei der Quotient ganzzahlig ist. Es handelt sich also um die Modulo-Operation.
Es gibt verschiedene mathematische Funktionen:
double sqrt(double x) | Quadratwurzel |
double cos(double x) | Kosinus |
double sin(double x) | Sinus |
double tan(double x) | Tangens |
double pow(double x, double y) | x hoch y (x > 0) |
double exp(double x) | Exponentialfunktion |
double log(double x) | natürlicher Logarithmus |
double abs(double x) | Absolutwert |
usw.
Alle diese Funktionen sind in einer Java-Klasse namens „Math“ definiert. Bei ihrer Verwendung muss ihnen der Name der Klasse vorangestellt werden, in der sie definiert sind. Man schreibt also:
Die Definition der Klasse Math lautet wie folgt:
public final class java.lang.Math
extends java.lang.Object (I-§1.12)
{
// Felder
public final static double E; §1.10.1
public final static double PI; §1.10.2
// Methoden
public static double abs(double a); §1.10.3
public static float abs(float a); §1.10.4
public static int abs(int a); §1.10.5
public static long abs(long a); §1.10.6
public static double acos(double a); §1.10.7
public static double asin(double a); §1.10.8
public static double atan(double a); §1.10.9
public static double atan2(double a, double b); §1.10.10
public static double ceil(double a); §1.10.11
public static double cos(double a); §1.10.12
public static double exp(double a); §1.10.13
public static double floor(double a); §1.10.14
public static double §1.10.15
IEEEremainder(double f1, double f2);
public static double log(double a); §1.10.16
public static double max(double a, double b); §1.10.17
public static float max(float a, float b); §1.10.18
public static int max(int a, int b); §1.10.19
public static long max(long a, long b); §1.10.20
public static double min(double a, double b); §1.10.21
public static float min(float a, float b); §1.10.22
public static int min(int a, int b); §1.10.23
public static long min(long a, long b); §1.10.24
public static double pow(double a, double b); §1.10.25
public static double random(); §1.10.26
public static double rint(double a); §1.10.27
public static long round(double a); §1.10.28
public static int round(float a); §1.10.29
public static double sin(double a); §1.10.30
public static double sqrt(double a); §1.10.31
public static double tan(double a); §1.10.32
}
2.3.4.3. Prioritäten bei der Auswertung arithmetischer Ausdrücke
Die Priorität der Operatoren bei der Auswertung eines arithmetischen Ausdrucks ist wie folgt (von der höchsten zur niedrigsten Priorität):
[fonctions], [ ( )], [ *, /, %], [+, -]
Operatoren innerhalb desselben Blocks [ ] haben dieselbe Priorität.
2.3.4.4. Relationale Ausdrücke
Es gibt folgende Operatoren: <, <=, ==, !=, >, >=
Prioritätsreihenfolge
>, >=, <, <=
==, !=
Das Ergebnis eines relationalen Ausdrucks ist der Boolesche Wert false, wenn der Ausdruck falsch ist, andernfalls true.
Beispiel:
Vergleich zweier Zeichen
Gegeben seien zwei Zeichenfolgen C1 und C2. Diese können mit den Operatoren
<, <=, ==, !=, >, >=
Es werden dann ihre Codes ASCII, bei denen es sich um Zahlen handelt, miteinander verglichen. Zur Erinnerung: Gemäß der Reihenfolge ASCII gelten die folgenden Beziehungen:
Leerzeichen < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. < 'z'
Vergleich zweier Zeichenketten
Sie werden Zeichen für Zeichen verglichen. Die erste Ungleichheit, die zwischen zwei Zeichen auftritt, führt zu einer Ungleichheit gleicher Richtung bei den Zeichenketten.
Beispiele:
Vergleichen wir die Zeichenfolgen „Chat“ und „Chien“
Diese letzte Ungleichheit lässt den Schluss zu, dass „Katze“ < „Hund“ gilt.

Nehmen wir an, wir wollen die Zeichenfolgen „Katze“ und „Kätzchen“ vergleichen. Es herrscht durchgehend Gleichheit, bis die Zeichenfolge „Katze“ vollständig abgearbeitet ist. In diesem Fall wird die vollständig abgearbeitete Zeichenfolge als die „kleinere“ deklariert. Es gilt also die Beziehung
„Katze“ < „Kätzchen“.
Funktionen zum Vergleich zweier Zeichenfolgen
Die relationalen Operatoren <, <=, ==, !=, >, >= können hier nicht verwendet werden. Es müssen Methoden der Klasse String verwendet werden:
String chaine1, chaine2;
chaine1=…;
chaine2=…;
int i=chaine1.compareTo(chaine2);
boolean egal=chaine1.equals(chaine2)
Im obigen Beispiel hat die Variable i folgenden Wert:
0: wenn beide Zeichenfolgen gleich sind
1: wenn Zeichenfolge Nr. 1 > Zeichenfolge Nr. 2
-1: wenn Zeichenfolge Nr. 1 < Zeichenfolge Nr. 2
Die Variable egal nimmt den Wert true an, wenn die beiden Zeichenfolgen gleich sind.
2.3.4.5. Boolesche Ausdrücke
Die Operatoren sind & (and) ||(or) und ! (not). Das Ergebnis eines booleschen Ausdrucks ist ein Boolescher Wert.
Prioritätsreihenfolge ! , &&, ||
Beispiel:
Relationale Operatoren haben Vorrang vor den Operatoren && und ||.
2.3.4.6. Bitweise Verarbeitung
Die Operatoren
Seien i und j zwei ganze Zahlen.
i<<n | verschiebt i um n Bits nach links. Die eingehenden Bits sind Nullen. |
i>>n | verschiebt i um n Bits nach rechts. Ist i eine vorzeichenbehaftete Ganzzahl (signed char, int, long), bleibt das Vorzeichenbit erhalten. |
i & j | führt die bitweise logische ODER-Verknüpfung von i und j durch. |
i | j | führt die bitweise logische ODER-Verknüpfung von i und j durch. |
~i | ergänzt i auf 1 |
i^j | Erzeugt OU aus EXCLUSIF von i und j |
Das heißt
Operation | Wert |
i<<4 | 0x23F0 |
i>>4 | 0x0123 Das Vorzeichenbit bleibt erhalten. |
k>>4 | 0xFF12 Das Vorzeichenbit bleibt erhalten. |
i&j | 0x1023 |
i|j | 0xF33F |
~i | 0xEDC0 |
2.3.4.7. Kombination von Operatoren
a=a+b lässt sich als a+=b schreiben
a=a-b kann als a-=b geschrieben werden
Das Gleiche gilt für die Operatoren /, %, *, <<, >>, &, |, ^
So lässt sich beispielsweise a=a+2; als a+=2; schreiben
2.3.4.8. Inkrementierungs- und Dekrementierungsoperatoren
Die Schreibweise variable++ bedeutet variable=variable+1 oder auch variable+=1
Die Schreibweise variable-- bedeutet variable=variable-1 oder auch variable-=1.
2.3.4.9. Der Operator ?
Der Ausdruck expr_cond ? expr1:expr2 wird wie folgt ausgewertet:
1: Der Ausdruck expr_cond wird ausgewertet. Es handelt sich um einen bedingten Ausdruck, dessen Wert entweder „wahr“ oder „falsch“ ist
2: Ist er wahr, ist der Wert des Ausdrucks der von expr1. expr2 wird nicht ausgewertet.
3: Ist die Bedingung falsch, geschieht das Gegenteil: Der Wert des Ausdrucks ist der Wert von expr2. expr1 wird nicht ausgewertet.
Beispiel
i = (j > 4 ? j + 1 : j - 1);
wird der Variablen i zugewiesen:
j+1, wenn j>4, andernfalls j-1
Das entspricht dem Ausdruck if(j>4) i=j+1; else i=j-1;, ist jedoch prägnanter.
2.3.4.10. Allgemeine Operatorpriorität
() [] Funktion | gd |
! ~ ++ -- | dg |
new (Typ) Cast-Operatoren | dg |
* / % | gd |
+ - | gd |
<< >> | gd |
< <= > >= instanceof | gd |
== != | gd |
& | gd |
^ | gd |
| | gd |
&& | gd |
|| | gd |
? : | dg |
= += -= usw. . | dg |
gd: Gibt an, dass bei gleicher Priorität die Priorität von links nach rechts gilt. Das bedeutet, dass in einem Ausdruck, in dem Operatoren gleicher Priorität vorkommen, der Operator ganz links im Ausdruck zuerst ausgewertet wird. dg gibt eine Priorität von rechts nach links an.
2.3.4.11. Typumwandlungen
In einem Ausdruck ist es möglich, die Darstellung eines Wertes vorübergehend zu ändern. Dies wird als Typumwandlung oder im Englischen als „type casting“ bezeichnet. Die Syntax für die Typumwandlung eines Wertes in einem Ausdruck lautet: (Typ) Wert. Der Wert nimmt dann den angegebenen Typ an. Dies führt zu einer Änderung der Darstellung des Wertes.
Beispiel:
Hier muss der Typ von i oder j in „real“ geändert werden, da die Division sonst einen ganzzahligen und keinen reellen Quotienten ergibt.
i ist ein exakt auf 2 Byte codierter Wert
(float) i ist derselbe Wert, der als Gleitkommazahl über 4 Bytes approximativ kodiert ist
Es findet also eine Umkodierung des Werts von i statt. Diese Umkodierung erfolgt nur für die Dauer einer Berechnung, wobei die Variable i stets ihren Typ int beibehält.
2.4. Anweisungen zur Steuerung des Programmablaufs
2.4.1. Beenden
Mit der in der Klasse System definierten Methode exit kann die Ausführung eines Programms abgebrochen werden.
Funktion: Beendet den laufenden Prozess und gibt den Wert „status“ an den übergeordneten Prozess zurück
exit bewirkt die Beendigung des laufenden Prozesses und übergibt die Kontrolle an den aufrufenden Prozess. Der Wert von status kann von diesem verwendet werden. Unter DOS wird diese Variable status an DOS in der Systemvariablen ERRORLEVEL zurückgegeben, deren Wert in einer Batch-Datei überprüft werden kann. Unter Unix übernimmt die Variable $? den Wert von status, wenn die Befehlszeilen-Interpreter die Bourne-Shell (/bin/sh) ist.
Beispiel:
um das Programm mit einem Statuswert von 0 zu beenden.
2.4.2. Einfache Entscheidungsstruktur
syntaxe : if (condition) {actions_condition_vraie;} else {actions_condition_fausse;}
Hinweise:
- Die Bedingung steht in Klammern.
- Jede Aktion endet mit einem Semikolon.
- Die geschweiften Klammern werden nicht mit einem Semikolon abgeschlossen.
- Geschweifte Klammern sind nur erforderlich, wenn mehr als eine Aktion vorhanden ist.
- Die else-Klausel kann weggelassen werden.
- Es gibt kein „then“.
Das algorithmische Äquivalent dieser Struktur ist die if-then-else-Struktur:
Beispiel
if (x>0) { nx=nx+1;sx=sx+x;} else dx=dx-x;
Auswahlstrukturen können verschachtelt werden:
Manchmal tritt folgendes Problem auf:
public static void main(void){
int n=5;
if(n>1)
if(n>6)
System.out.println(">6");
else System.out.println("<=6");
}
Auf welches if bezieht sich im vorigen Beispiel das else? Die Regel lautet, dass sich ein else immer auf das nächstgelegene if bezieht: im Beispiel also auf if(n>6). Betrachten wir ein weiteres Beispiel:
public static void main(void)
{ int n=0;
if(n>1)
if(n>6) System.out.println(">6");
else; // else des if(n>6): nichts zu tun
else System.out.println("<=1"); // else der if(n>1)
}
Hier wollten wir ein else an das if(n>1) anhängen und kein else an das if(n>6). Aufgrund der vorherigen Anmerkung sind wir gezwungen, ein „else“ für if(n>6) einzufügen, in dem sich keine Anweisung befindet.
2.4.3. Fallstruktur
Die Syntax lautet wie folgt:
switch(expression) {
case v1:
actions1;
break;
case v2:
actions2;
break;
. .. .. .. .. ..
default: actions_sinon;
}
Hinweise
- Der Wert des Steuerausdrucks darf nur eine ganze Zahl oder ein Zeichen sein.
- Der Steuerausdruck steht in Klammern.
- Die Klausel default kann fehlen.
- Die Werte vi sind mögliche Werte des Ausdrucks. Wenn der Ausdruck den Wert vi hat, werden die Aktionen hinter der case-Klausel vi ausgeführt.
- Die Anweisung break verlässt die case-Struktur. Fehlt sie am Ende des Anweisungsblocks mit dem Wert vi, wird die Ausführung mit den Anweisungen des Werts vi+1 fortgesetzt.
Beispiel
In der Algorithmik
selon la valeur de choix
cas 0
arrêt
cas 1
exécuter module M1
cas 2
exécuter module M2
sinon
erreur<--vrai
findescas
In Java
int choix, erreur;
switch(choix){
case 0: System.exit(0);
case 1: M1();break;
case 2: M2();break;
default: erreur=1;
}
2.4.4. Wiederholungsstruktur
2.4.4.1. Anzahl der Wiederholungen bekannt
Syntax
for (i=id;i<=if;i=i+ip){
actions;
}
Hinweise
- Die drei Argumente von for stehen in Klammern.
- Die drei Argumente von for sind durch Semikolons getrennt.
- Jede Aktion von for endet mit einem Semikolon.
- Die geschweifte Klammer ist nur erforderlich, wenn mehr als eine Aktion vorhanden ist.
- Auf die geschweifte Klammer folgt kein Semikolon.
Das algorithmische Äquivalent ist die Struktur pour:
was sich in eine Struktur tantque übersetzen lässt:
2.4.4.2. Anzahl der Wiederholungen unbekannt
In Java gibt es zahlreiche Strukturen für diesen Fall.
„while“-Schleife
while(condition){
actions;
}
Die Schleife wird so lange ausgeführt, wie die Bedingung erfüllt ist. Es kann sein, dass die Schleife nie ausgeführt wird.
Hinweise:
- Die Bedingung steht in Klammern.
- Jede Aktion wird mit einem Semikolon abgeschlossen.
- Die geschweifte Klammer ist nur erforderlich, wenn mehr als eine Aktion vorhanden ist.
- Auf die geschweifte Klammer folgt kein Semikolon.
Die entsprechende algorithmische Struktur ist die „solange“-Struktur:
„Wiederhole, bis“-Struktur (do while)
Die Syntax lautet wie folgt:
do{
instructions;
}while(condition);
Die Schleife wird so lange wiederholt, bis die Bedingung falsch wird oder solange die Bedingung wahr ist. Hier wird die Schleife mindestens einmal durchlaufen.
Hinweise
- Die Bedingung steht in Klammern.
- Jede Aktion wird mit einem Semikolon abgeschlossen.
- Die geschweifte Klammer ist nur erforderlich, wenn mehr als eine Aktion vorhanden ist.
- Auf die geschweifte Klammer folgt kein Semikolon.
Die entsprechende algorithmische Struktur ist die „Wiederhole … bis“-Struktur:
Struktur für „for“
Die Syntax lautet wie folgt:
for(instructions_départ;condition;instructions_fin_boucle){
instructions;
}
Die Schleife wird so lange durchlaufen, wie die Bedingung wahr ist (sie wird vor jedem Schleifendurchlauf ausgewertet). Instructions_départ werden vor dem ersten Eintritt in die Schleife ausgeführt. Instructions_fin_boucle werden nach jedem Schleifendurchlauf ausgeführt.
Anmerkungen
- Die drei Argumente von for stehen in Klammern.
- Die drei Argumente von for sind durch Semikolons getrennt.
- Jede Aktion der for-Schleife endet mit einem Semikolon.
- Die geschweifte Klammer ist nur erforderlich, wenn mehr als eine Aktion vorhanden ist.
- Auf die geschweifte Klammer folgt kein Semikolon.
- Die verschiedenen Anweisungen in instructions_depart und instructions_fin_boucle sind durch Kommas getrennt.
Die entsprechende algorithmische Struktur sieht wie folgt aus:
Beispiele
Die folgenden Programme berechnen alle die Summe der ersten n ganzen Zahlen.
1 for(i=1, somme=0;i<=n;i=i+1)
somme=somme+a[i];
2 for (i=1, somme=0;i<=n;somme=somme+a[i], i=i+1);
3 i=1;somme=0;
while(i<=n)
{ somme+=i; i++; }
4 i=1; somme=0;
do somme+=i++;
while (i<=n);
Anweisungen zur Schleifenverwaltung
break | Beendet die Schleife „for“, „while“ oder „do ... while“. |
continue | springt zur nächsten Iteration der Schleifen „for“, „while“ und „do ... while“ |
2.5. Die Struktur eines Java-Programms
Ein Java-Programm, das weder benutzerdefinierte Klassen noch andere Funktionen als die Hauptfunktion main verwendet, kann folgende Struktur haben:
public class test1{
public static void main(String arg[]){
… code du programme
}// main
}// Klasse
Die Funktion main, auch Methode genannt, wird bei der Ausführung eines Java-Programms als Erstes aufgerufen. Sie muss zwingend die folgende Signatur aufweisen:
public static void main(String arg[]){
oder
public static void main(String[] arg){
Der Name des Arguments arg kann beliebig sein. Es handelt sich um ein Array von Zeichenketten, die die Argumente der Befehlszeile darstellen. Wir werden später noch darauf zurückkommen.
Wenn Funktionen verwendet werden, die Ausnahmen erzeugen können, die nicht detailliert behandelt werden sollen, kann der Programmcode mit einer try/catch-Klausel umschlossen werden:
public class test1{
public static void main(String arg[]){
try{
… code du programme
} catch (Exception e){
// Fehlerbehandlung
}// try
}// main
}// Klasse
Am Anfang des Quellcodes und vor der Klassendefinition finden sich üblicherweise Anweisungen zum Importieren von Klassen. Zum Beispiel:
import java.io.*;
public class test1{
public static void main(String arg[]){
… code du programme
}// main
}// Klasse
Nehmen wir ein Beispiel. Angenommen, es gibt folgende Schreibanweisung:
die java auf den Bildschirm schreibt. In diesem einfachen Befehl steckt eine Menge:
- System ist eine Klasse, deren vollständiger Name java.lang.System lautet
- out ist eine Eigenschaft dieser Klasse vom Typ java.io.PrintStream, einer weiteren Klasse
- println ist eine Methode der Klasse java.io.PrintStream.
Wir wollen diese Erklärung nicht unnötig verkomplizieren, da sie zu früh kommt und das Verständnis des Begriffs „Klasse“ voraussetzt, der noch nicht behandelt wurde. Eine Klasse lässt sich mit einer Ressource vergleichen. In diesem Fall benötigt der Compiler Zugriff auf die beiden Klassen java.lang.System und java.io.PrintStream. Die Hunderte von Java-Klassen sind in Archiven verteilt, die auch als Pakete (Packages) bezeichnet werden. Die am Anfang des Programms platzierten Anweisungen import dienen dazu, dem Compiler mitzuteilen, welche externen Klassen das Programm benötigt (d. h. diejenigen, die verwendet, aber nicht in der zu kompilierenden Quelldatei definiert sind). In unserem Beispiel benötigt unser Programm also die Klassen java.lang.System und java.io.PrintStream. Dies wird mit der Anweisung import angegeben. Am Anfang des Programms könnte man schreiben:
Da ein Java-Programm üblicherweise mehrere Dutzend externe Klassen verwendet, wäre es mühsam, alle erforderlichen Funktionen import zu schreiben. Die Klassen wurden in Paketen zusammengefasst, sodass man das gesamte Paket importieren kann. Um also die Pakete java.lang und java.io zu importieren, schreibt man:
Das Paket java.lang enthält alle Java-Basisklassen und wird vom Compiler automatisch importiert. Daher schreibt man letztendlich nur:
2.6. Ausnahmebehandlung
Viele Java-Funktionen können Ausnahmen, d. h. Fehler, auslösen. Wir sind bereits auf eine solche Funktion gestoßen, nämlich die Funktion readLine:
String ligne=null;
try{
ligne=IN.readLine();
System.out.println("ligne="+ligne);
} catch (Exception e){
affiche(e);
System.exit(2);
}// try
Wenn eine Funktion eine Ausnahme auslösen kann, zwingt der Java-Compiler den Programmierer, diese zu behandeln, um fehlerresistentere Programme zu erhalten: Ein unkontrollierter „Absturz“ einer Anwendung muss stets vermieden werden. Hier löst die Funktion readLine eine Ausnahme aus, wenn nichts zu lesen ist, weil beispielsweise der Eingabestrom geschlossen wurde. Die Behandlung einer Ausnahme erfolgt nach folgendem Schema:
try{
appel de la fonction susceptible de générer l'exception
} catch (Exception e){
traiter l'exception e
}
instruction suivante
Wenn die Funktion keine Ausnahme auslöst, wird zur nächsten Anweisung übergegangen; andernfalls wird in den Hauptteil der Klausel catch verzweigt und anschließend zur nächsten Anweisung übergegangen. Beachten Sie folgende Punkte:
- e ist ein abgeleitetes Objekt vom Typ Exception. Man kann genauer sein, indem man Typen wie IOException, SecurityException, ArithmeticException usw. verwendet: Es gibt etwa zwanzig Ausnahmetypen. Mit der Anweisung „catch (Exception e)“ gibt man an, dass alle Ausnahmetypen abgefangen werden sollen. Wenn der Code der Klausel try mehrere Ausnahmetypen auslösen kann, möchte man möglicherweise genauer vorgehen und die Ausnahme mit mehreren Klauseln vom Typ catch abfangen:
try{
appel de la fonction susceptible de générer l'exception
} catch (IOException e){
traiter l'exception e
}
} catch (ArrayIndexOutOfBoundsException e){
traiter l'exception e
}
} catch (RunTimeException e){
traiter l'exception e
}
instruction suivante
- Den Klauseln try/catch kann eine finally-Klausel hinzugefügt werden:
try{
appel de la fonction susceptible de générer l'exception
} catch (Exception e){
traiter l'exception e
}
finally{
code exécuté après try ou catch
}
instruction suivante
Unabhängig davon, ob eine Ausnahme vorliegt oder nicht, wird der Code der Klausel finally immer ausgeführt.
- Die Klasse Exception verfügt über eine Methode getMessage(), die eine Meldung zurückgibt, in der der aufgetretene Fehler detailliert beschrieben wird. Wenn man diesen anzeigen möchte, schreibt man also:
catch (Exception ex){
System.err.println("L'erreur suivante s'est produite : "+ex.getMessage());
...
}//catch
- Die Klasse Exception verfügt über eine Methode toString(), die eine Zeichenkette zurückgibt, die den Typ der Ausnahme sowie den Wert der Eigenschaft Message angibt. Man kann also schreiben:
catch (Exception ex){
System.err.println ("L'erreur suivante s'est produite : "+ex.toString());
...
}//catch
Man kann auch schreiben:
Hier handelt es sich um eine Operation vom Typ „Zeichenkette + Exception“, die vom Compiler automatisch in „Zeichenkette + Exception.toString()“ umgewandelt wird, um die Verkettung zweier Zeichenketten durchzuführen.
Das folgende Beispiel zeigt eine Ausnahme, die durch die Verwendung eines nicht vorhandenen Array-Elements ausgelöst wird:
// Tabellen
// Importe
import java.io.*;
public class tab1{
public static void main(String[] args){
// Deklaration und Initialisierung eines Arrays
int[] tab=new int[] {0,1,2,3};
int i;
// Anzeige eines Arrays mit einer for-Schleife
for (i=0; i<tab.length; i++)
System.out.println("tab[" + i + "]=" + tab[i]);
// Auslösen einer Ausnahme
try{
tab[100]=6;
}catch (Exception e){
System.err.println("L'erreur suivante s'est produite : " + e);
}//try-catch
}//main
}//Klasse
Die Ausführung des Programms liefert folgende Ergebnisse:
tab[0]=0
tab[1]=1
tab[2]=2
tab[3]=3
L'erreur suivante s'est produite : java.lang.ArrayIndexOutOfBoundsException
Hier ist ein weiteres Beispiel, in dem die Ausnahme behandelt wird, die durch die Zuweisung einer Zeichenkette zu einer Zahl ausgelöst wird, wenn die Zeichenkette keine Zahl darstellt:
// Importe
import java.io.*;
public class console1{
public static void main(String[] args){
// Erstellung eines Eingabestroms
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
}catch(Exception ex){}
// Der Name wird abgefragt
System.out.print("Nom : ");
// Antwort lesen
String nom=null;
try{
nom=IN.readLine();
}catch(Exception ex){}
// Nach dem Alter wird gefragt
int age=0;
boolean ageOK=false;
while ( ! ageOK){
// Frage
System.out.print("âge : ");
// Antwort lesen und überprüfen
try{
age=Integer.parseInt(IN.readLine());
ageOK=true;
}catch(Exception ex) {
System.err.println("Age incorrect, recommencez...");
}//try-catch
}//while
// Abschließende Anzeige
System.out.println("Vous vous appelez " + nom + " et vous avez " + age + " ans");
}//Main
}//Klasse
Einige Ausführungsergebnisse:
E:\data\serge\MSNET\c#\bases\1>console1
Nom : dupont
âge : xx
Age incorrect, recommencez...
âge : 12
Vous vous appelez dupont et vous avez 12 ans
2.7. Kompilieren und Ausführen eines Java-Programms
Kompilieren und führen Sie das folgende Programm aus:
// Import von Klassen
import java.io.*;
// Testklasse
public class coucou{
// Hauptfunktion
public static void main(String args[]){
// Bildschirmanzeige
System.out.println("coucou");
}//main
}//Klasse
Die Quelldatei, die die vorherige Klasse coucou enthält, muss zwingend den Namen coucou.java tragen:
Die Kompilierung und Ausführung eines Java-Programms erfolgt in einem Fenster mit der Bezeichnung DOS. Die ausführbaren Dateien javac.exe (Compiler) und java.exe (Interpreter) befinden sich im Verzeichnis bin des Installationsverzeichnisses von JDK:
E:\data\serge\JAVA\classes\paquetages\personne>dir "e:\program files\jdk14\bin\java?.exe"
07/02/2002 12:52 24 649 java.exe
07/02/2002 12:52 28 766 javac.exe
Der Compiler javac.exe analysiert die .java-Quelldatei und erzeugt eine kompilierte .class-Datei. Diese kann vom Prozessor nicht sofort ausgeführt werden. Sie benötigt einen Java-Interpreter (java.exe), der als virtuelle Maschine oder JVM (Java Virtual Machine) bezeichnet wird. Ausgehend vom Zwischencode in der .class-Datei generiert die virtuelle Maschine Befehle, die für den Prozessor des Computers, auf dem sie ausgeführt wird, spezifisch sind. Es gibt Java-Virtual-Machines für verschiedene Betriebssysteme (Windows, Unix, Mac OS, ...). Eine .class-Datei kann von jeder dieser Virtual Machines und somit auf jedem Betriebssystem ausgeführt werden. Diese systemübergreifende Portabilität ist einer der größten Vorteile von Java.
Kompilieren wir das vorherige Programm:
E:\data\serge\JAVA\ESSAIS\intro1>"e:\program files\jdk14\bin\javac" coucou.java
E:\data\serge\JAVA\ESSAIS\intro1>dir
10/06/2002 08:42 228 coucou.java
10/06/2002 08:48 403 coucou.class
Führen wir die erzeugte Datei .class aus:
Es ist zu beachten, dass in dem obigen Ausführungsbefehl das Suffix .class der auszuführenden Datei coucou.class nicht angegeben wurde. Es ist implizit enthalten. Befindet sich das Verzeichnis „bin“ der Datei „JDK“ im Verzeichnis „PATH“ des Rechners „DOS“, muss der vollständige Pfad zu den ausführbaren Dateien javac.exe und java.exe nicht angegeben werden. Man schreibt dann einfach
2.8. Argumente des Hauptprogramms
Die Hauptfunktion main akzeptiert als Parameter ein String-Array: String[]. Dieses Array enthält die Argumente der Befehlszeile, mit der die Anwendung gestartet wurde. Wenn also das Programm P mit dem folgenden Befehl gestartet wird:
und die Funktion „main“ wie folgt deklariert ist:
erhält man arg[0]="arg0", arg[1]="arg1" … Hier ein Beispiel:
import java.io.*;
public class param1{
public static void main(String[] arg){
int i;
System.out.println("Nombre d'arguments="+arg.length);
for (i=0;i<arg.length;i++)
System.out.println("arg["+i+"]="+arg[i]);
}
}
Die folgenden Ergebnisse wurden erzielt:
2.9. Übergabe von Parametern an eine Funktion
Die vorangegangenen Beispiele zeigten ausschließlich Java-Programme mit nur einer Funktion, nämlich der Hauptfunktion main. Das folgende Beispiel veranschaulicht, wie Funktionen verwendet werden und wie der Informationsaustausch zwischen Funktionen erfolgt. Die Parameter einer Funktion werden immer als Wert übergeben: Das bedeutet, dass der Wert des tatsächlichen Parameters in den entsprechenden formalen Parameter kopiert wird.
import java.io.*;
public class param2{
public static void main(String[] arg){
String S="papa";
changeString(S);
System.out.println("Paramètre effectif S="+S);
int age=20;
changeInt(age);
System.out.println("Paramètre effectif age="+age);
}
private static void changeString(String S){
S="maman";
System.out.println("Paramètre formel S="+S);
}
private static void changeInt(int a){
a=30;
System.out.println("Paramètre formel a="+a);
}
}
Die folgenden Ergebnisse wurden erzielt:
Die Werte der effektiven Parameter „papa“ und 20 wurden in die formalen Parameter S und a kopiert. Diese wurden anschließend geändert. Die effektiven Parameter blieben hingegen unverändert. Dabei ist der Typ der effektiven Parameter zu beachten:
- S ist eine Objektreferenz auf c.a.d, also die Adresse eines Objekts im Speicher
- age ist ein ganzzahliger Wert
2.10. Das Beispiel „Steuern“
Wir schließen dieses Kapitel mit einem Beispiel ab, auf das wir im weiteren Verlauf dieses Dokuments noch mehrfach zurückkommen werden. Wir wollen ein Programm schreiben, mit dem sich die Steuer eines Steuerpflichtigen berechnen lässt. Wir betrachten den vereinfachten Fall eines Steuerpflichtigen, der lediglich sein Gehalt anzugeben hat:
- Wir berechnen die Anzahl der Anteile des Arbeitnehmers nbParts = nbEnfants/2 + 1, wenn er unverheiratet ist, nbEnfants/2 + 2, wenn er verheiratet ist, wobei nbEnfants die Anzahl seiner Kinder ist.
- Wenn er mindestens drei Kinder hat, erhält er einen halben Anteil zusätzlich
- sein steuerpflichtiges Einkommen R wird berechnet als R = 0,72 * S, wobei S sein Jahresgehalt ist
- man berechnet seinen Familienkoeffizienten QF = R / nbParts
- Man berechnet seine Steuer I. Betrachten wir die folgende Tabelle:
12620,0 | 0 | 0 |
13.190 | 0,05 | 631 |
15640 | 0,1 | 1290,5 |
24.740 | 0,15 | 2072,5 |
31.810 | 0,2 | 3309,5 |
39.970 | 0,25 | 4900 |
48360 | 0,3 | 6898,5 |
55.790 | 0,35 | 9316,5 |
92.970 | 0,4 | 12106 |
127.860 | 0,45 | 16.754,5 |
151250 | 0,50 | 23.147,5 |
172.040 | 0,55 | 30.710 |
195.000 | 0,60 | 39312 |
0 | 0,65 | 49062 |
Jede Zeile enthält 3 Felder. Um die Steuer I zu berechnen, wird die erste Zeile gesucht, in der QF <= Feld 1 gilt. Wenn beispielsweise QF = 23000 ist, wird die Zeile
Die Steuer I beträgt dann 0,15*R – 2072,5*nbParts. Wenn QF so ist, dass die Beziehung QF <= Feld1 niemals erfüllt ist, werden die Koeffizienten der letzten Zeile verwendet. Hier:
was die Steuer I = 0,65 * R – 49062 * nbParts ergibt.
Das entsprechende Java-Programm lautet wie folgt:
import java.io.*;
public class impots{
// ------------ main
public static void main(String arg[]){
// Daten
// Grenzen der Steuerklassen
double Limites[]={12620, 13190, 15640, 24740, 31810, 39970, 48360,55790, 92970, 127860, 151250, 172040, 195000, 0};
// auf die Anzahl der Anteile angewandter Koeffizient
double Coeffn[]={0, 631, 1290.5, 2072.5, 3309.5, 4900, 6898.5, 9316.5,12106, 16754.5, 23147.5, 30710, 39312, 49062};
// das Programm
// Erstellung des Tastatureingabestroms
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
}
catch(Exception e){
erreur("Création du flux d'entrée", e, 1);
}
// Der Familienstand wird abgerufen
boolean OK=false;
String reponse=null;
while(! OK){
try{
System.out.print("Etes-vous marié(e) (O/N) ? ");
reponse=IN.readLine();
reponse=reponse.trim().toLowerCase();
if (! reponse.equals("o") && !reponse.equals("n"))
System.out.println("Réponse incorrecte. Recommencez");
else OK=true;
} catch(Exception e){
erreur("Lecture état marital",e,2);
}
}
boolean Marie = reponse.equals("o");
// Anzahl der Kinder
OK=false;
int NbEnfants=0;
while(! OK){
try{
System.out.print("Nombre d'enfants : ");
reponse=IN.readLine();
try{
NbEnfants=Integer.parseInt(reponse);
if(NbEnfants>=0) OK=true;
else System.err.println("Réponse incorrecte. Recommencez");
} catch(Exception e){
System.err.println("Réponse incorrecte. Recommencez");
}// try
} catch(Exception e){
erreur("Lecture état marital",e,2);
}// try
}// while
// Gehalt
OK=false;
long Salaire=0;
while(! OK){
try{
System.out.print("Salaire annuel : ");
reponse=IN.readLine();
try{
Salaire=Long.parseLong(reponse);
if(Salaire>=0) OK=true;
else System.err.println("Réponse incorrecte. Recommencez");
} catch(Exception e){
System.err.println("Réponse incorrecte. Recommencez");
}// try
} catch(Exception e){
erreur("Lecture Salaire",e,4);
}// try
}// while
// Berechnung der Anzahl der Anteile
double NbParts;
if(Marie) NbParts=(double)NbEnfants/2+2;
else NbParts=(double)NbEnfants/2+1;
if (NbEnfants>=3) NbParts+=0.5;
// steuerpflichtiges Einkommen
double Revenu;
Revenu=0.72*Salaire;
// Familienquotient
double QF;
QF=Revenu/NbParts;
// Ermittlung der Steuerklasse entsprechend QF
int i;
int NbTranches=Limites.length;
Limites[NbTranches-1]=QF;
i=0;
while(QF>Limites[i]) i++;
// die Steuer
long impots=(long)(i*0.05*Revenu-Coeffn[i]*NbParts);
// Das Ergebnis wird angezeigt
System.out.println("Impôt à payer : " + impots);
}// Hauptbild
// ------------ Fehler
private static void erreur(String msg, Exception e, int exitCode){
System.err.println(msg+"("+e+")");
System.exit(exitCode);
}// Fehler
}// Klasse
Die folgenden Ergebnisse wurden erzielt:
C:\Serge\java\impots\1>java impots
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : 3
Salaire annuel : 200000
Impôt à payer : 16400
C:\Serge\java\impots\1>java impots
Etes-vous marié(e) (O/N) ? n
Nombre d'enfants : 2
Salaire annuel : 200000
Impôt à payer : 33388
C:\Serge\java\impots\1>java impots
Etes-vous marié(e) (O/N) ? w
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? q
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : q
Réponse incorrecte. Recommencez
Nombre d'enfants : 2
Salaire annuel : q
Réponse incorrecte. Recommencez
Salaire annuel : 1
Impôt à payer : 0