2 Die einfachsten Anweisungen 2- 1 Die einfachsten Anweisungen Inhalt Einführung Datentypen Arithmetische Operatoren Mathematische Funktionen Mehrfache Zuweisungen Übungsaufgaben Einführung Wir wollen unser erstes Programm /* Mehrzeiliger Kommentar: Das "Hello World" Beispiel. */ public class HelloWorld { public static void main (String args[]) { System.out.println("Hello World"); // Kommentar } } ausweiten. Zunächst sollen die einzelnen Zeilen erläutert werden. public class HelloWorld {... } public static void main (String args[]) {... } System.out.println("Hello World"); Leitet die Definition einer Klasse ein. Ein Java-Programm besteht aus einer Reihe von Klassen. Die Klasse, die main enthält, muß öffentlich sein (public). Die Java-Datei muß den gleichen Namen haben, wie die öffentliche Klasse, die in ihr deklariert ist. Definition eines Unterprogramms mit Namen main. Dieses Unterprogramm wird vom Java-Interpreter automatisch gestartet. Es muß auch öffentlich (public) sein und statisch (static). Das Unterprogramm main des Beispiels Unterprogramm gibt kein Ergebnis zurück (void) und benutzt seine Parameter (Strings args[]) nicht. Aufruf des Unterprogramms println im 2 Die einfachsten Anweisungen 2- 2 Object System.out. Dieses Unterprogramm kann den als Parameter überegebenen String "Hello World" auf der Kommandozeile ausgeben. Die Zeile ist ein Beispiel für eine Anweisung. Jede Anweisung wird mit einem ; abgeschlossen. ... // Kommentar /* ... */ Ein Zeilenkommentar. Wird vom Compiler ignoriert. Mehrzeiliger Kommentar. Der Compiler ignoriert alles zwischen /* und */ Wir wollen nun dieses Programm verändern. Dazu kopieren wir die Datei HelloWorld.java nach Test.java. cp HelloWorld.java Test.java (bzw. copy für DOS) und verändern den Inhalt folgendermaßen. public class Test { public static void main (String args[]) { int n; n=3*4; System.out.println(n); } } Dies berechnet das Produkt 12 und gibt das Ergebnis aus. Beachten Sie, daß sich auch der Name der Klasse geändert hat. Es gibt in diesem Beispiel folgende neue Sprachelemente. int n; Deklaration einer Variablen mit Namen n. Die Variable wird auf dem Stack gespeichert und steht nur in dem Unterprogramm main lokal zur Verfügung. Nach Beendigung des Unterprogramms steht sie nicht mehr zur Verfügung. Die Variable ist vom Typ int (integer, d.h. ganze Zahl). Sie kann Werte von -2'147'483'648 bis 2'147'483'647 annehmen. Die allgemeine Form der Variablendeklaration lautet datentyp variablenname; n=3*4; Dies ist eine Zuweisung. An n wird der Wert zugewiesen, der sich aus der Berechnung des Ausdrucks 3*4 ergibt. Dieser Ausdruck ist vom Typ int, da er eine Operation mit zwei int-Konstanten ist. Offenbar ergibt sich der Typ eines Ausdrucks aus dem Typ der Operanden. 2 Die einfachsten Anweisungen 2- 3 Datentypen Der Typ von Konstanten, wie 3 und 4, ergibt sich aus Ihrer Schreibweise. Bei Zahlen ohne Komma ist er int, bei Zahlen mit Komma double, z.B. 3.4, -1.55 oder auch 1.5e10. Ein Ausdruck bleibt solange vom Typ int als keine double-Werte in ihm enthalten sind. Achtung! Der Ausdruck 1/3 ergibt 0, da er ganzzahlig berechnet wird. Nun können wir etwa einen komplizierteren Ausdruck berechnen. public class Test { public static void main (String args[]) { double x=1.5,y; y=1+x+x*x/2+x*x*x/6+x*x*x*x/24; System.out.println("y = "+y); } } Es ist also möglich mehrere Variablen in einer Zeile zu deklarieren und ihnen auch gleich Werte zuzuweisen. Außerdem wird hier die Variable x als Operand in Ausdrücken eingesetzt. Man beachte die Addition eines Strings und einer double-Variablen bei der Ausgabe. Hier wird zuerst der double-Wert zu einem String umgewandelt und danach werden beide Strings aneinandergehängt. Dieses Programm wird folgendermaßen übersetzt und ausgeführt. D:\java\kurs>javac Test.java D:\java\kurs>java Test y = 4.3984375 Es gibt folgende elementare Datentypen. Alle Variablen dieser Typen werden analog den Beispielen deklariert und auf dem Stack erzeugt. Konstanten Wertemenge Datentyp -2^15 ... 2^15-1 short int 3, -3, 0, 0x3FF (hexadezimal), 0377 (octal) long 3l, -30000000000l -2^63 ... 2^63-1 float double byte -2^31 ... 2^31-1 ca 6-stellige Mantisse und zweistelliger Exponent. 3.1415, 1e20, 1e- ca. 16-stellige Dezimal-Mantisse und 310, -1E10 stelliger Exponent. 0 ... 2^8-1=255. Normale Speichereinheit. 2 Die einfachsten Anweisungen char 'A', 'a', ' ', '\t', '\n', '\xFE', '\u0121' (Unicode) boolean true, false 2- 4 Zwei byte-Character in Unicode. Wenn das oberste Byte 0 ist, so entspricht dies dem normalen Zeichensatz. In anderen Sprachen ist dieser Datentyp nur ein Byte lang. Wahr oder falsch. Automatische Umwandlungen sind nur erlaubt, wenn das Ziel der Wert in jedem Fall aufnehmen kann, etwa. int n=3; long l=n; // automatische Umwandlung Umgekehrt ist ein type cast notwendig. long l=20000; int n=(int)l; // type cast von long nach int Damit lassen sich Datentypen beliebig ineinander umwandeln. Für Fehler trägt der Programmierer die Verantwortung. public class Test { public static void main (String args[]) { long c=1000000000000l; // das l ist notwendig! System.out.println(c); // druckt korrekten Wert System.out.println((int)c); // druckt -727379968 } } Bei Überlauf wird kein Laufzeitfehler erzeugt. Division durch 0 oder ähnliche Fehler erzeugen allerdings eine arithmetic exception. Exceptions und ihre Behandlung vertagen wir vorerst. Arithmetische Operatoren Für die arithmetischen Datentypen (alle außer boolean) sind die üblichen Operatoren +,-,*,/ und % (modulo) definiert. Das Ergebnis ist jeweils vom gleichen Typ. Deswegen int n=3; System.out.println(n/4); // druckt 0 Vergleiche von Zahlen ergeben true oder false vom Typ boolean. Es gibt die Vergleiche <, <= (kleiner oder gleich), >, >=, == (gleich), != (ungleich). Beispiel: double x=3; System.out.println(1/x>=0.3); // druckt true Ausdrücke vom Typ boolean werden mit && (und) und || (oder) verknüpft. Sie werden ins Gegenteil verkehrt mit ! (nicht). Die Ausführungsreihenfolge ist streng festgelegt, entspricht aber der üblichen Konvention. System.out.println((3.0+7.0)/(4.0*5.0+80.0)); // druckt 0.1 System.out.println((3.0+7)/(4*5+8)); // druckt 0.1 System.out.println((double)(3+7)/(4*5+8)); // druckt auch 0.1 System.out.println((3+7)/(4*5+80)); // druckt aber 0 !!! Außerdem gibt es eine Reihe von speziellen bitweisen Operatoren für Zahlen, nämlich | 2 Die einfachsten Anweisungen 2- 5 (oder), & (und) ^ (entweder oder) und ^ (bitweises Komplement, NOT). Daneben gibt es noch Operatoren, die bitweise nach rechts und links schieben, nämlich >> (Verschieben nach rechts, wobei negative Zahlen negativ bleiben), << und >>> (Verschieben nach rechts mit Auffüllen von 0). Z.B. entspricht n<<2 einer Multiplikation von n mit 4. Diese Operatoren sind nur dann von Interesse, wenn Zahlen im Dualsystem behandelt werden sollen. Es gibt auch die Oparatoren ++ und --, und zwar nachgestellt und vorausgestellt. Diese Operatoren erhöhen, bzw. erniedrigen, einen ganzahligen Wert um 1. ++n tut dies vor der Verwendung von n, und n++ danach. Man kann diese Operatoren auch als Anweisungen verwenden. Beispiel: int i=1; i++; System.out.println(i); // druckt 2. Außerdem existieren Kombinationen zwischen Operatoren und =. Beispiel int i=1; i+=2; System.out.println(i); // druckt 3. Mathematische Funktionen Die mathematischen Funktionen sind in der Klasse Math statisch erklärt. Sie werden daher wie im folgenden Beispiel aufgerufen: System.out.println(Math.exp(1)); // Druckt den Wert von e Es gibt die üblichen Funktionen abs, sin, cos, exp, log, asin, acos und sqrt definiert. Daneben existieren Funktionen mit zwei Variablen, wie pow (berechnet x^y), atan2 (berechnet den Winkel von x,y), max und min. Alle diese Funktionen müssen mit vorangestelltem Math. aufgerufen werden. Daneben existieren die Funktionen floor und ceil, die zur nächsten ganzzahligen Funktion ab-, bzw. aufrunden. Die Funktion round rundet zur nächsten ganzen Zahl, ergibt aber einen long-Wert. Schließlich erzeugt die Funktion random eine Zufallszahl zwischen 0 und 1. Mehrfache Zuweisungen Man kann auch mehrere Zuweisungen gleichzeitig durchführen. int n,m; n=m=3; Dies liegt daran, daß eine Zuweisung wie m=3 in Wirklichkeit ein Ergebnis (nämlich 3) hat, das dann von n= weiterverwendet wird. Normalerweise wird dieses Ergebnis verworfen. Man kann das Ergebnis auch in anderen Fällen verwenden. Jedoch führt dies meist zu schlecht lesbarem Code. Beispielsweise ist nicht auf den ersten Blick klar, wie double a; 2 Die einfachsten Anweisungen 2- 6 double y=Math.sin(a=Math.PI/4)); eigentlich funktioniert. Dagegen liest sich double a=Math.PI/4; double y=Math.sin(a); wesentlich leichter. Übungsaufgaben 1. Schreiben Sie ein Programm, das den Umfang eines Kreises mit Radius 2.0 ausgibt. Geben Sie auch den Radius des Kreises aus. Die Ausgabe sollte so aussehen: Der Umfang eines Kreises mit Radius 2.0 ist 12.566370614359172 2. Was ist das Ergebnis des Ausdrucks 1000000*1000000? Warum entsteht dieses Ergebnis? 3. Was ergibt 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1-1.0? Warum ist das nicht exakt 0.0? 4. Berechnen Sie (1+1/n)^n für wachsende Werte von n. Wie groß muß man n wählen, damit dieser Ausdruck von e weniger als 0.01 entfernt ist? 5. Geben Sie das Zeichen mit der Nummer 124 aus. 6. Geben Sie einen Ausdruck an, der genau dann wahr ist, wenn x im Intervall [1,2] liegt. 7. Probieren Sie aus, was passiert, wenn man die Wurzel aus -1 berechen will. Lösungen (bitte vorher selbst probieren!). Aufgaben ohne Lösung 1. Man kann mit dem Datentyp char Rechnen. Er wird dann wie int behandelt, indem sein Code in eine Zahl umgewandelt wird. Berechnen Sie den 10. Buchstaben nach dem 'A'. Wieviele Buchstaben liegen zwischen 'A' und 'Z'? Wo liegen die kleinen, und wo die großen Buchstaben, wo die Zahlen? 2. Testen Sie die Verschiebe-Operatoren >>, >>> und <<. Was bewirken diese Operatoren und warum? 3. Was passiert bei einem type cast von double nach int. Rundet der Rechner oder schneidet er die Zahl ab? Wie rundet er? Wie behandelte er negative Zahlen? 4. Testen Sie, was passiert wenn n++ zweimal in einem Ausdruck vorkommt, oder wenn n++ vorkommt und danach n nochmals. Was ist der Unterschied zu ++n? 2 Die einfachsten Anweisungen 2- 7 5. Was passiert, wenn long auf int umgewandelt wird. Wird immer der höherwertige Teil abgeschnitten. Bleiben negative Zahlen negativ? Zurück zum Java-Kurs