From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
+Wie in den meisten anderen Programmiersprachen gehören auch in
+Java Ausdrücke zu den kleinsten ausführbaren Einheiten
+eines Programms. Sie dienen dazu, Variablen einen Wert zuzuweisen,
+numerische Berechnungen durchzuführen oder logische Bedingungen
+zu formulieren.
+
+
+Ein Ausdruck besteht immer aus mindestens einem Operator und einem
+oder mehreren Operanden, auf die der Operator angewendet wird. Nach
+den Typen der Operanden unterscheidet man numerische, relationale,
+logische, bitweise, Zuweisungs- und sonstige
+Operatoren. Jeder Ausdruck hat einen Rückgabewert, der durch
+die Anwendung des Operators auf die Operanden entsteht. Der Typ des
+Rückgabewerts bestimmt sich aus den Typen der Operanden und der
+Art des verwendeten Operators.
+
+
+Neben der Typisierung ist die Stelligkeit eines Operators
+von Bedeutung. Operatoren, die lediglich ein Argument erwarten, nennt
+man einstellig, solche mit zwei Argumenten zweistellig.
+Beispiele für einstellige Operatoren sind das unäre Minus
+(also das negative Vorzeichen) oder der logische Nicht-Operator. Arithmetische
+Operatoren wie Addition oder Subtraktion sind zweistellig. Darüber
+hinaus gibt es in Java - wie in C - auch den dreiwertigen Fragezeichenoperator.
+
+
+Für die richtige Interpretation von Ausdrücken muss man
+die Bindungs- und Assoziativitätsregeln
+der Operatoren kennen. Bindungsregeln beschreiben die Reihenfolge,
+in der verschiedene Operatoren innerhalb eines Ausdrucks ausgewertet
+werden. So besagt beispielsweise die bekannte Regel »Punktrechnung
+vor Strichrechnung«, dass der Multiplikationsoperator eine höhere
+Bindungskraft hat als der Additionsoperator und demnach in Ausdrücken
+zuerst ausgewertet wird. Assoziativität beschreibt die Auswertungsreihenfolge
+von Operatoren derselben Bindungskraft, also beispielsweise die Auswertungsreihenfolge
+einer Kette von Additionen und Subtraktionen. Da Summationsoperatoren
+linksassoziativ sind, wird beispielsweise der Ausdruck a-b+c
+wie (a-b)+c ausgewertet und
+nicht wie a-(b+c).
+
+
+Neben ihrer eigentlichen Funktion, einen Rückgabewert zu produzieren,
+haben einige Operatoren auch Nebeneffekte.
+Als Nebeneffekt bezeichnet man das Verhalten eines Ausdrucks, auch
+ohne explizite Zuweisung die Inhalte von Variablen zu verändern.
+Meist sind diese Nebeneffekte erwünscht, wie etwa bei der Verwendung
+der Inkrement- und Dekrementoperatoren. Komplexere Ausdrücke
+können wegen der oftmals verdeckten Auswertungsreihenfolge der
+Teilausdrücke jedoch unter Umständen schwer verständliche
+Nebeneffekte enthalten und sollten deshalb mit Vorsicht angewendet
+werden.
+
+
+Im Gegensatz zu vielen anderen Programmiersprachen ist in Java die
+Reihenfolge der Auswertung der Operanden
+innerhalb eines Teilausdrucks wohldefiniert. Die Sprachdefinition
+schreibt explizit vor, den linken Operanden eines Ausdrucks vollständig
+vor dem rechten Operanden auszuwerten. Falls also beispielsweise i
+den Wert 2 hat, dann ergibt der Ausdruck (i=3)
+* i in jedem Fall den Wert 9 und nicht 6.
+
+
+Neben der natürlichen Auswertungsreihenfolge, die innerhalb eines
+Ausdrucks durch die Bindungs- und Assoziativitätsregeln vorgegeben
+wird, läßt sich durch eine explizite Klammerung
+jederzeit eine andere Reihenfolge erzwingen. Während das Ergebnis
+des Ausdrucks 4+2*5 wegen der
+Bindungsregeln 14 ist, liefert (4+2)*5
+das Resultat 30. Die Regeln für die Klammerung von Teilausdrücken
+in Java gleichen denen aller anderen Programmiersprachen und brauchen
+daher nicht weiter erläutert zu werden.
+
+
+In Java gibt es ein Konzept, das sich Definite Assignment
+nennt. Gemeint ist damit die Tatsache, dass jede lokale Variable vor
+ihrer ersten Verwendung definitiv initialisiert sein muss. Das wünscht
+sich eigentlich zwar auch jeder Programmierer, aber in Java wird dies
+durch den Compiler sichergestellt! Dazu muss im Quelltext eine Datenflussanalyse
+durchgeführt werden, die jeden möglichen Ausführungspfad
+von der Deklaration einer Variablen bis zu ihrer Verwendung ermittelt
+und sicherstellt, dass kein Weg existiert, der eine Initialisierung
+auslassen würde.
+
+
+
+
+Die folgende Methode Test läßt
+sich beispielsweise deshalb nicht fehlerfrei kompilieren, weil k
+vor der Ausgabeanweisung nicht initialisiert wird, wenn i
+kleiner 2 ist:
+
+
+
+
+
+
+ Titel
+ Inhalt
+ Suchen
+ Index
+ DOC
+ Handbuch der Java-Programmierung, 5. Auflage
+
+ <<
+ <
+ >
+ >>
+ API
+ Kapitel 5 - Ausdrücke
+
+
+
+
+
+5.1 Eigenschaften von Ausdrücken
+
+
+
+
+
+
+
+Listing 5.1: Fehler beim Kompilieren durch unvollständige Initialisierung
+
+
+
+
+
+001 public static void Test(int i)
+002 {
+003 int k;
+004 if (i >= 2) {
+005 k = 5;
+006 }
+007 System.out.println(k);
+008 }
+
+
+Ein solches Verhalten des Compilers ist natürlich höchst +wünschenswert, denn es zeigt einen tatsächlichen +Fehler an, der sonst unbemerkt geblieben wäre. Daß die +Datenflussanalyse allerdings auch Grenzen hat, zeigt das folgende +Beispiel, bei dem ebenfalls ein Compiler-Fehler auftritt: + + +
+
+
+
+001 public static void Test(int i)
+002 {
+003 int k;
+004 if (i < 2) {
+005 k = 5;
+006 }
+007 if (i >= 2) {
+008 k = 6;
+009 }
+010 System.out.println(k);
+011 }
+
+ |
+
+Natürlich kann hier k nicht +uninitialisiert bleiben, denn eine der beiden Bedingungen ist immer +wahr. Leider gehen die Fähigkeiten der Compiler noch nicht so +weit, dies zu erkennen. + +
+Es wäre in diesem Fall natürlich vernünftiger gewesen, +den else-Zweig +an die erste Verzweigung anzuhängen und damit die zweite ganz +einzusparen. + +
+In Wirklichkeit funktioniert die Datenflussanalyse bei vernünftigem +Programmierstil recht gut. Die wenigen Fälle, in denen der Compiler +sich irrt, können in der Regel durch explizite Initialisierungen +aufgelöst werden. +
| Titel + | Inhalt + | Suchen + | Index + | DOC + | Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 + |
| << + | < + | > + | >> + | API + | © 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de + |