Lektion 2, Teil 1: Java-Kontrollstrukturen (2) 88 / 534 Programmiersprachen sind formale Sprachen Schreibweisen von Elementen einer Programmiersprache müssen exakt definiert sein. Programmiersprachen besitzen ähnlich wie natürliche Sprachen Grammatiken. Die Grammatiken sind bei Programmiersprachen durch formale Regeln (sogenannte Produktionsregeln) definiert. Die Syntax (siehe nächste Folie) wird meist durch eine kontextfreie Grammatik festgelegt. 89 / 534 Syntax, Semantik Die Syntax einer (Programmier-) Sprache regelt die erlaubten Kombinationen von Sprachelementen Fragment aus NumberOfDigits //"Zubereitung" n = reader.readInt(); d = 1; while(n>9 { n = n / 10; d = d + 1; } System.out.println(d); Finden Sie den syntaktischen Fehler ? 90 / 534 Syntax, Semantik Die Semantik regelt die Bedeutung eines Programmteils Fragment aus NumberOfDigits //"Zubereitung" n = reader.readInt(); d = 1; while(n>9); { n = n / 10; d = d + 1; } System.out.println(d); Finden Sie den semantischen Fehler ? 91 / 534 Syntax, Semantik Die Semantik regelt die Bedeutung eines Programmteils Fragment aus NumberOfDigits //"Zubereitung" n = reader.readInt(); d = 1; while(n>=9) { n = n / 10; d = d + 1; } System.out.println(d); Finden Sie den semantischen Fehler ? 92 / 534 Syntaxfehler und Semantikfehler Syntaxfehler: Zeigen sich beim Compilieren Semantikfehler: Zeigen sich zur Laufzeit des Programmes 93 / 534 Extended Backus-Naur Form (EBNF) Die EBNF ist eine Menge von Produktionen (Ersetzungregeln), in denen links ein Symbol und rechts Symbolfolgen stehen, durch die das Symbol ersetzt werden darf. Die Extended Backus-Naur Form (EBNF) definiert eine Grammatik lexikalische Struktur: IntLiteral IntLiteral Digit Sign ⇒ ⇒ ⇒ [Sign] Digit+ ”0”|”1”|”2”|”3”|”4”|”5”|”6”|”7”|”8”|”9” ”+”|”-” -107 42 94 / 534 Extended Backus-Naur Form (EBNF) lexikalische Struktur: IntLiteral IntLiteral Digit Sign ⇒ ⇒ ⇒ [Sign] Digit+ ”0”|”1”|”2”|”3”|”4”|”5”|”6”|”7”|”8”|”9” ”+”|”-” -107 42 Syntaxdiagramm IntLiteral Digit 0 1 2 sign digit 9 95 / 534 Sonderzeichen einer EBNF Wir verwenden folgende Notation1 [...] Symbole zwischen eckigen Klammern sind optional und dürfen einmal vorkommen oder auch weggelassen werden. ...∗ Symbole mit nachfolgendem Stern können beliebig oft wiederholt werden, oder können auch weggelassen werden ...+ Symbole mit nachfolgendem Pluszeichen müssen mindestens einmal vorkommen und können beliebig oft wiederholt werden (...) Gruppieren von Symbolen | Trennzeichen für die Alternativen in einer Produktionsregel (siehe oben). 1 In der Java Sprachbeschreibung auf http://java.sun.com/docs/books/jls/third edition/html/syntax.html#18.1 wird eine alternative aber gleichmächtige Notation mit “ ... ” benutzt. 96 / 534 Namen für Variablen (engl. Identifier) Variablennamen müssen mit einem Buchstaben beginnen und dürfen nur Buchstaben, Zahlen und die Sonderzeichen “$” und “ ” enthalten. Identifier Letter Identifier ⇒ ⇒ “a” | “b” | “c” | “d” | “e” | | “j” | “k” | “l” | “m” | “n” | “s” | “t” | “u” | “v” | “w” | “A” | “B” | “C” | “D” | “E” | “J” | “K” | “L” | “M” | “N” | “S” | “T” | “U” | “V” | “W” Letter ( Letter | Digit )* “f” | | “o” | “x” | “F” | “O” | “X” “g” | | “p” | “y” | “G” | “P” | “Y” “h” | | “q” | “z” | “H” | “Q” | “Z” “i” | “r” | “I” | “R” | “$” | “ ” 97 / 534 Produktionsregeln für numerische Literale Literal IntLiteral DoubleLiteral DoubleLiteral DoubleLiteral DoubleLiteral Exponent DoubleSuffix ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ IntLiteral | DoubleLiteral | StringLiteral | CharLiteral [Sign] Digit+ [Sign] Digit+ “.” Digit* [Exponent] [DoubleSuffix] [Sign] Digit* “.” Digit+ [Exponent] [DoubleSuffix] [Sign] Digit+ Exponent [DoubleSuffix] [Sign] Digit+ [DoubleSuffix] (“E”|“e”) [Sign] Digit+ “D”|“d” +20e10 Beispiel Literal 10d .1e2 10D 10e1 gültig? X X X X Literal 20.e10d 20.78e-30D 10e20e-10 20e gültig? X X nein nein 98 / 534 EBNF Ableitungsbaum +20e10 DoubleLiteral z }| { Exponent [Sign] Digit+ z }| { ↓ ↓ (“E”|“e”) [Sign]Digit+ z}|{ z}|{ z}|{ z}|{ + 20 e 10 99 / 534 Statement ParExpression while ( Expression Statement ) Expression1 Block Expression2 Beispiel (EBNF Baum) Expression3 Primary Der EBNF Ableitungsbaum einer komplexeren Anweisung ... { Expression2Rest InfixOp Expression3 Statement Identifier Primary StatementExpression ; StatementExpression ; Literal Expression IntegerLiteral I i < Expression 5 Expression1 AssignmentOperator Expression1 Expression2 while ( i <= 5 ) { system.out.print(i); i+=1; } } BlockStatements Statement Expression2 Expression1 Expression2 I Expression3 Expression3 Expression3 Primary Primary . system Primary IdentifierSuffix Identifier Identifier Identifier out . print Arguments ( Expression Literal Identifier ) i IntegerLiteral += 1 Expression1 Expression2 Expression3 Primary Identifier i 100 / 534 EBNF für Anweisungen in Java Eine Anweisung kann sein: Definitionen von Variablen Zuweisungen ... (folgt Statement Definition Type Assignment später) ⇒ Definition | Assignment ⇒ [”final”] Type Identifier [”=” Expression] ”;” ⇒ ”int” | ”double” | ”char” | ”String” ⇒ Identifier ”=” Expression ”;” Beispiel final double PI = 3.14159; double radius = 2; double area; area = radius * radius * PI; boolean validRadius = radius >= 0; 101 / 534 EBNF für Ausdrücke in Java Expression Expression Expression Expression UnaryOperator BinaryOperator IncDecOperator Expression Expression Expression Type ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ ⇒ DoubleLiteral | IntLiteral | Identifier Expression BinaryOperator Expression UnaryOperator Expression ”(” Expression ”)” ”+” | ”-” ”+” | ”-” | ”*” | ”/” | ”%” ”++” | ”--” IncDecOperator Identifier Identifier IncDecOperator “(” Type “)” Expression ”int” | ”double” | ”char” rest + 1 -(2+3) (2+3) ++i i++ (int) 2.5 102 / 534 Wiederholung: Werte und Typen, Ergänzung boolean Definition (Literal) Ein Literal ist die Bezeichnung eines Wertes in einer Programmiersprache Wert 10 7 21.2 3.1415 a programming is fun WAHR FALSCH Literal in Java 10 7 21.2 3.1415 ’a’ "programming is fun" true false 103 / 534 Boole’sche Ausdrücke Ausdrücke, die Wahrheitswerte liefern (George Boole, Mathematiker, 1815 − 1864) Beispiel Ausdruck 2<5 2>5 2>=2 Wert WAHR FALSCH WAHR 104 / 534 Boole’sche Operatoren Operanden: Zahlenwerte (numerische Literale, Variablen, Ausdrücke) Ergebnis: Wahrheitswert 3 < 5 |{z} |{z} |{z} Zahl Operator Zahl 105 / 534 Boole’sche Operatoren < <= > >= == != kleiner kleiner oder gleich größer größer oder gleich ist gleich ist nicht gleich 106 / 534 Weitere Beispiele für Boole’sche Ausdrücke int i; char ch; i = 98; ch = ’b’; Ausdruck ’a’ < ’b’ ch == ’b’ ch == ’a’ ch == i Wert true true false true 107 / 534 Priorität von Boole’schen Operatoren Boole’sche Operatoren binden schwächer als arithmetische Operatoren Ausdruck 4 + 3 < 8 14 != 20 - 6 Wert true false 108 / 534 Variablen vom Typ boolean Einer boolean-Variable kann ein boolean-Wert zugewiesen werden Beispiel boolean angemeldet; angemeldet = true; boolean validTemperature = celcius > -273.16; 109 / 534 Kontrollstrukturen in Java Verzweigungen: if-Anweisung Anweisungsblöcke Wiederholungen (Schleifen): I I while-Anweisung for-Anweisung ... 110 / 534 Wiederholung: GGT - Euklidischer Algorithmus start m← n← r ← rest von m / n r <> 0 nein ja m←n n←r r ← rest von m / n m← n← rest ← m mod n rest > 0 m←n n ← rest rest ← m mod n n→ m 28 20 8 m 100 45 10 n 20 8 4 n 45 10 5 r 8 4 0 r 10 5 0 n→ ende 111 / 534 Beispiel: GGT Differenz Algorithmus m← n← m 6= n m>n ja nein m ←m−n n ←n−m m→ Äquivalent zum Euklidischen Alg.: gleiches Ein-/Ausgabeverhalten Effizienz: Euklidischer Alg. ist effizienter (weniger Schritte notwendig, unabhängig von Programmiersprache) m 28 8 8 8 4 m 100 55 10 10 10 10 10 5 n 20 20 12 4 4 n 45 45 45 35 25 15 5 5 112 / 534 GGT - Differenz Algorithmus Einlesen n start m← n← while (m!=n) if (m>n) m = m - n; else n = n - m; m→ einlesen m,n nein m != n ja m>n nein ja m=m-n nein n=n-m ausgabe m stop 113 / 534 if-Anweisung mit else-Teil mit else-Teil (Verzweigung, Alternative): boole’scher Ausdruck WAHR FALSCH Anweisung1 Anweisung2 if ( boole’scher Ausdruck ) Anweisung1 else Anweisung2 114 / 534 if-Anweisung ohne else-Teil ohne else-Teil (bedingte Anweisung) boole’scher Ausdruck WAHR FALSCH Anweisung ∅ if ( boole’scher Ausdruck ) Anweisung 115 / 534 if-Anweisung: Beispiel In einer Firma soll für Überstunden 1.5 mal soviel Lohn bezahlt werden... if (wochenstunden > 40) gehalt = stundenlohn*40 + 1.5*stundenlohn*(wochenstunden - 40); else gehalt = stundenlohn*wochenstunden; 116 / 534 if-Anweisung: Beispiel Die if-Anweisung muss nicht immer einen else-Teil haben: bonus = 0; gehalt = wochenstunden * stundenlohn; if (wochenstunden > 40) bonus = 0.5*stundenlohn*(wochenstunden - 40); gehalt = gehalt + bonus; 117 / 534 Beispiel: Maximum von 3 Werten a > b j n a > c b > c j n j n max ← a max ← c max ← b max ← c 118 / 534 Beispiel: Maximum von 3 Werten if(a > b) if(a > c) max = else max = else if(b > c) max = else max = a; c; b; c; 119 / 534 Anweisungsblöcke Fassen eine Sequenz von Anweisungen mit { und } zusammen Können eingesetzt werden, wo eine einzelne Anweisung erwartet wird Statement ⇒ ”{” Statement ”}” if ( bool’scher Ausdruck ) Anweisung1 else Anweisung2 if ( radius >= 0 ) { area = radius * radius * PI; System.out.print("Die Fläche des Kreises mit Radius "); System.out.print(radius); System.out.print(" ist "); System.out.println(area); } else 120 / 534 System.out.println("Eingabefehler!"); Problem des ”dangling-else” Zu welchem if gehört das else in diesem Beispiel? if ( Bedingung 1 ) if (Bedingung 2 ) Anweisung 1 else Anweisung 2 if ( Bedingung 1 ) if ( Bedingung 2 ) Anweisung 1 else Anweisung 2 X if ( Bedingung 1 ) if ( Bedingung 2 ) Anweisung 1 else Anweisung 2 Einrückung entspricht hier NICHT der Interpretation durch den Compiler 121 / 534 else bezieht sich immer auf das textuell letzte freie if Einrückungen dienen der Übersichtlichkeit für Menschen, werden aber vom Compiler nicht berücksichtigt 122 / 534 Explizite Zuordnung durch Block-Klammern if ( Bedingung 1 ) { if ( Bedingung 2 ) Anweisung 1 else Anweisung 2 } if ( Bedingung 1 ) { if ( Bedingung 2 ) Anweisung 1 } else Anweisung 2 123 / 534 Logische Operatoren akzeptieren boolean-Werte (Ausdrücke, Variablen, Wahrheitsliterale) als Operanden liefern als Ergebnis einen boolean-Wert Logische Operatoren && || ^ ! logisches logisches logisches logisches Und Oder exklusives Oder Nicht 124 / 534 Logische Operatoren And false false true true && && && && false true false true → → → → false false false true || || || || false true false true → → → → false true true true Xor false false true true ^ ^ ^ ^ false true false true → → → → false true true false Or false false true true Not !false !true → → true false 125 / 534 Zusammengesetzte Bedingungen if ( month == 4 || month == 6 || month == 9 || month == 11 ) days = 30; else if ( month == 2 ) days = 28; else days = 31; 126 / 534 Beispiel: Maximum von 3 Werten if(a > b) if(a > c) max = else max = else if(b > c) max = else max = a; c; b; c; 127 / 534 Beispiel: Maximum von 3 Werten if(a > b && a > c) max = a; if(a > b && a <= c) max = c; if(a <= b && b < c) max = c; ... 128 / 534 Priorität von logischen Operatoren logische Operatoren binden schwächer als Boole’sche Operatoren Ausdruck 4 + 3 < 8 || false 14 != 20 - 6 || 2 < 2 Wert true false 129 / 534 GGT - Differenz Algorithmus Einlesen n start m← n← while (m!=n) if (m>n) m = m - n; else n = n - m; m→ einlesen m,n nein m != n ja m>n nein ja m=m-n nein n=n-m ausgabe m stop 130 / 534 Kontrollstrukturen in Java Verzweigungen: if-Anweisung Anweisungsblöcke Wiederholungen (Schleifen): I I while-Anweisung for-Anweisung ... 131 / 534 Syntax der while-Anweisung Bedingung Anweisung while ( boole’scher Ausdruck ) Anweisung 132 / 534 Syntax der for-Anweisung Die for-Anweisung lässt sich auch in eine while-Anweisung umschreiben eignet sich aber oft wegen der kompakten Schreibweise... Startanweisung Bedingung Anweisung Fortschaltanweisung for ( Startanweisung; Bedingung; Fortschaltanweisung ) Anweisung 133 / 534 Schleifen: Die for-Schleife int summe = int i = 1; while (i <= summe = i = i + } 0; n) { summe + i; 1; int summe = 0; for (int i = 1; i <= n; i++) { summe = summe + i; } 134 / 534 GGT: Differenz Algorithmus Einlesen n start m = reader.nextInt(); n = reader.nextInt(); while (m!=n) if (m>n) m = m - n; else n = n - m; System.out.println(m); einlesen m,n nein m != n ja m>n nein ja m=m-n nein n=n-m ausgabe m stop 135 / 534 Zusammenfassung Lektion 2 Strukturebenen einer Programmiersprache: I I Syntax (Beschreibung mit EBNF) Semantik Bool’sche Werte, Variablen, Operatoren, Ausdrücke Logische Operatoren Kontrollstrukturen in Java I if,while,for,switch 136 / 534 Lektion 2, Teil 2 (Repetitorium): Java-Programme, Bibliotheksmethoden, Scanner 137 / 534 Bibliotheksmethoden System.out.println: zum Erzeugen von Ausgaben am Bildschirm mit nachfolgendem Zeilenvorschub System.out.print: zum Erzeugen von Ausgaben am Bildschirm ohne Zeilenvorschub Math.sqrt: Berechnen der Wurzel. z.B. Math.sqrt(4) wertet zu 2.0 (Typ double) aus. Math.sqrt liefert im Gegensatz zu den oberen 2 Methoden einen Wert zurück ... Der Funktionsumfang der Laufzeitbibliothek wird als ”Java Application Programming Interface” bezeichnet (Java-API). Interface = Schnittstelle. 138 / 534 Mathematische Bibliotheksmethoden So wie die Operatoren eine bestimmte Anzahl an Operanden benötigen, erwarten die Methoden eine bestimmte Anzahl an Argumenten. mehrere Argumente werden durch Beistriche getrennt die mathematischen Methoden werden so wie Ausdrücke ausgewertet und liefern einen Funktionswert (meist double) zurück. Beispiel (Berechnung einer Potenz) Der double-Variablen x soll der Wert 37 zugewiesen werden: x = Math.pow(3,7); Argumente 139 / 534 Mathematische Bibliotheksmethoden Beispiel (Verschachtelungen) 3 berechne x = 33 : berechne x = (33 )3 : x = Math.pow(3, Math.pow(3,3)); x = Math.pow(Math.pow(3,3), 3); 140 / 534 Bibliotheksmethode Math.hypot() Beispiel (Math.hypot()) a=2 Pythagoras: c=2.5 c 2 = a2 + b 2 p a2 + b 2 c = b=1.5 141 / 534 Bibliotheksmethode Math.hypot() Berechnung der Länge der Hypotenuse, wenn in a,b die Längen der Katheten gespeichert sind: double a = 2; double b = 1.5; double c = Math.hypot(a,b); das gleiche Ergebnis erhält man mit double a = 2; double b = 1.5; double c = Math.sqrt(Math.pow(a,2)+Math.pow(b,2)); 142 / 534 Mathematische Bibliotheksmethoden: Übersicht Methodenname Math.sin Math.cos Math.hypot Math.exp Math.pow Math.max Math.min Bedeutung Sinus Cosinus Hypotenuse e-Funktion Potenz Maximum Minimum Argumente double double double , double double double , double double , double double , double Beispiel Math.sin(3.1415) Math.cos(3.1415) Math.hypot(2,1.5) Math.exp(1.0) Math.pow(3,7) Math.max(3.0,5) Math.min(3,5) 143 / 534 Mathematische Bibliotheksmethoden: Übersicht Mathematik sin(π) cos(π) q 2 22 + 32 e1 37 max(3, 5) min(3, 5) Java Math.sin(3.1415) Math.cos(3.1415) Wert 9.265358966049026E-5 -0.9999999957076562 Math.hypot(2,1.5) Math.exp(1.0) Math.pow(3,7) Math.max(3.0,5) Math.min(3,5) 2.5 2.7182818284590455 6561.0 5.0 3 144 / 534 Vordefinierte Variablen Mathematik π e Java Math.PI Math.E Beispiel Math.cos(Math.PI) Math.log(Math.E) Wert -1.0 1.0 145 / 534 Bibliotheksmethoden: Werte am Bildschirm ausgeben System.out.println kann auch Zahlenwerte ausgeben: double radius = 5.5; double area = radius * radius * Math.PI; System.out.println("Die Fläche des Kreises mit Radius "); System.out.println(radius); System.out.println(" ist "); System.out.println(area); erzeugt am Bildschirm Die Fläche des Kreises mit Radius 5.5 ist 95.03317777109125 146 / 534 Bibliotheksmethoden: Ausgabe mit oder ohne Zeilenvorschub System.out.println I mit abschliessendem Zeilenvorschub System.out.print I ohne abschliessenden Zeilenvorschub 147 / 534 Bibliotheksmethoden: Ausgabe mit oder ohne Zeilenvorschub double radius = 5.5; double area = radius * radius * Math.PI; System.out.print("Die Fläche des Kreises mit Radius "); System.out.print(radius); System.out.print(" ist "); System.out.println(area); erzeugt am Bildschirm Die Fläche des Kreises mit Radius 5.5 ist 95.03317777109125 148 / 534 Bibliotheksmethoden: Werte oder Text einlesen mit Scanner //die folgende Zeile muss im Programmcode stehen Scanner reader = new Scanner(System.in); /* Echonumber: Eine Zahl wird eingelesen und am Bildschirm ausgegeben */ System.out.print("Bitte eine Zahl eingeben: "); int input = reader.nextInt(); System.out.print("Sie haben die Zahl "); System.out.print(input); System.out.println(" eingegeben."); 149 / 534 Methoden: Werte oder Text einlesen mit Scanner Der Wert 7 wird beim Ablauf des Programmes vom Benutzer eingegeben... Bitte eine Zahl eingeben: 7 Sie haben die Zahl 7 eingegeben. 7 ist Eingabe des Benutzers 150 / 534 String: + Operator zum verketten String output = "Sie haben die Zahl " + input + " eingegeben"; System.out.print(output); erzeugt Sie haben die Zahl 7 eingegeben. Achtung: System.out.print(’a’+’b’); erzeugt 195 151 / 534 String: Zeilenumbrüche String output = "eins\nzwei\ndrei"; System.out.print(output); erzeugt eins zwei drei 152 / 534 String: Beispiel für Verkettung mit Zeilenumbrüchen //Draw a triangle int zeilen = 4; String output = ""; for (int i = 0; i<zeilen; i++) { for (int j = 0; j<=i; j++) { output += "*"; } output += "\n"; } System.out.print(output); erzeugt * ** *** **** 153 / 534 String: Länge einer Zeichenkette mit length() Die Länge einer Zeichenkette kann mit der Methode length() bestimmt werden. String output = "eins\nzwei\ndrei"; int len = output.length(); System.out.print(len); erzeugt 14 154 / 534 Vergleich von Zeichenketten (String) Zeichenketten sollten nicht mit dem Operator == auf Gleichheit überprüft werden. stattdessen sollte equals verwendet werden. Grund: String ist Referenztyp (siehe später) String input; input = reader.next(); if (input.equals("ja")) { ... } X 155 / 534 Scanner-Methoden Methode nextInt() nextDouble() next() ? .. . zum Einlesen von ganzen Zahlen Kommazahlen einer Zeichenkette eines einzelnen Zeichens 156 / 534 Scanner-Methoden: Beispiel Punkteschema Gegeben sei folgendes Notenschema: Punkte Note [0 - 50[ 5 [50 - 68[ 4 [68 - 80[ 3 [80 - 90[ 2 [90 - 100] 1 157 / 534 Scanner-Methoden: Einlesen von int-Werten String grade; Scanner reader = new Scanner(System.in); System.out.print("Bitte Punktestand eingeben: "); int points = reader.nextInt(); if (points >= 90) grade = "sehr gut"; else if (points >= 80) grade = "gut"; else if (points >= 68) grade = "befriedigend"; else if (points >= 50) grade = "genuegend"; else grade = "nicht genuegend"; System.out.println("Note: " + grade); 158 / 534 Scanner-Methoden: Einlesen von Strings next() liest ein Wort bis exklusive zum nächsten Leerzeichen oder Zeilenvorschub ein nextLine() liest bis zum Zeilenende (inkl. Zeilenvorschub) ein H a l l o W e l t \n String a = reader.next(); String b = reader.nextLine(); Variable a b bekommt ”Wert” "Hallo" " Welt" 159 / 534 Scanner-Methoden: Einlesen von Strings next() liest ein Wort bis exklusive zum nächsten Leerzeichen oder Zeilenvorschub ein nextLine() liest bis zum Zeilenende (Zeilenvorschub) ein H a l l o \n W e l t \n String a = reader.nextLine(); String b = reader.next(); Variable a b bekommt ”Wert” "Hallo" "Welt" 160 / 534 Scanner-Methoden: Einlesen von Strings next() liest ein Wort bis exklusive zum nächsten Leerzeichen oder Zeilenvorschub ein nextLine() liest bis zum Zeilenende (inkl. Zeilenvorschub) ein H a l l o \n W e l t \n String a = reader.next(); String b = reader.nextLine(); Variable a b bekommt ”Wert” "Hallo" "" 161 / 534 Scanner-Methoden: Einlesen von Strings next() liest ein Wort bis exklusive zum nächsten Leerzeichen oder Zeilenvorschub ein nextLine() liest bis zum Zeilenende (Zeilenvorschub) ein H a l l o W e l t \n String a = reader.nextLine(); String b = reader.next(); //blockiert(wartet) Variable a bekommt ”Wert” "Hallo Welt" b 162 / 534 Scanner-Methoden: Einlesen von einzelnen Zeichen Es gibt keine Methode zum Einlesen eines Zeichens. Folgender Befehl liefert aber als Abhilfe das erste Zeichen eines eingelesenen Wortes: Scanner reader = new Scanner(System.in); char answer; answer = reader.next().charAt(0); if (answer == ’j’) System.out.println("JA"); else System.out.println("NEIN"); 163 / 534 Allg. Form des Aufrufs von Scanner-Methoden 1 Ein Scanner-Objekt erzeugen (Erklärung folgt später)... Scanner objektname = new Scanner(System.in); Diese Anweisung sollte zusammen mit den Variablendefinitionen (am Anfang des Programms) stehen. 2 Wert einlesen (Scanner-Methoden verwenden) variablenname = objektname.nextInt(); 164 / 534 GGT: Differenz Algorithmus m = reader.nextInt(); n = reader.nextInt(); while (m!=n) if (m>n) m = m - n; else n = n - m; System.out.println(m); 165 / 534 ”Programmrahmen” class GGTDiff { public static void main (String[] args) { Hier kommt der obige Programmcode hinein... } } 166 / 534 import java.util.Scanner; public class GGTDiff { public static void main (String[] args) { int n; int m; Scanner reader = new Scanner(System.in); n = reader.nextInt(); m = reader.nextInt(); while ( n != m ) { if ( m > n ) { m = m - n; } else { n = n - m; } } System.out.println(m); } } 167 / 534 ”Programmrahmen”: allgemeine Form public class programmname { public static void main (String[] args) { Hier kommt der Programmcode hinein... } } 168 / 534 Scanner: Überprüfung der Eingaben Folgende Methoden stehen zur Überprüfung der Eingaben zur Verfügung liefern Information über die Eingabe in Form von boolean-Werten I I I hasNext(): liefert false wenn das Ende der Eingabe (”End of File”) erreicht wurde, sonst true hasNextInt(): liefert false wenn das nächste Wort der Eingabe nicht als int-Wert gelesen werden kann, sonst true hasNextDouble(): liefert false wenn das nächste Wort der Eingabe nicht als double-Wert gelesen werden kann, sonst true Weitere Info: http://java.sun.com/javase/6/docs/api/?java/util/Scanner.html 169 / 534 Gültigkeitsbereiche von Variablen Eine Variable ist nur innerhalb des Blocks in dem sie definiert wurde gültig... public class Test { public static void main(String[] args) { { int i = 2; } System.out.print(i); //Fehler i nicht definiert } } 170 / 534 Gültigkeitsbereiche von Variablen Eine Variable ist nur innerhalb des Blocks in dem sie definiert wurde gültig... public class Test { public static void main(String[] args) { int i = 2; { System.out.print(i); //Ausgabe: 2 } } } 171 / 534 Lebensdauer von Variablen Beim Verlassen eines Programmblocks werden alle darin definierten Variablen verworfen In diesem Beispiel wird bei jedem Schleifendurchlauf eine Variable square erzeugt und wieder verworfen // Bildet die Summe der Quadrate von 1 bis n int n = 10; int sum = 0; int i = 0; while (i <= n) { i++; int square = i*i; sum += square; } 172 / 534 Namenskollision Namenskollision: Eine definierte Variable darf nicht erneut definiert werden (solange Sie noch gültig ist) // Bildet die Summe der Quadrate von 1 bis n int n = 10; int sum = 0; int i = 0; while (i <= n) { i++; int n = i*i; // Fehler: n ist bereits definiert sum += n; } 173 / 534 Quelltext Definition Quelltext, Code, Quellcode (engl. source code): = vom Programmierer verfasster Text in einer formalen Sprache (Programmiersprache wie z.B. Java). Dient als “Quelle” zur Weiterverarbeitung. Zum Schreiben eines Quelltexts wird ein Texteditor benutzt der den Quelltext in einer Quelldatei speichert. 174 / 534 Übersetzer, Virtuelle Maschine public class Sum10 { public static void main ( String [] args ) { int summe; int zahl; summe = 0; zahl = 1; while (zahl < 11) { summe = summe + zahl; zahl = zahl + 1; } } } Quelltext liest erzeugt Compiler 00000000h: 00000010h: 00000020h: 00000030h: 00000040h: 00000050h: 00000060h: 00000070h: 00000080h: 00000090h: 000000a0h: 000000b0h: 000000c0h: 000000d0h: 000000e0h: 000000f0h: 00000100h: 00000110h: 00000120h: CA 00 03 6E 6D 61 53 31 75 2F 00 1D 00 00 00 60 00 00 00 FE 0D 28 65 61 6E 6F 30 6D 4F 00 00 01 08 00 3C 00 08 0C BA 07 29 4E 69 67 75 2E 31 62 02 01 00 00 00 1C 00 00 00 BE 00 56 75 6E 2F 72 6A 30 6A 00 00 07 09 16 04 1E 0A 01 00 0E 01 6D 01 53 63 61 01 65 01 01 00 00 03 60 00 00 00 00 01 00 62 00 74 65 76 00 63 00 00 00 01 3C 3D 07 09 0A 00 00 04 65 16 72 46 61 10 74 04 00 00 00 04 A7 00 00 00 31 06 43 72 28 69 69 0C 6A 00 00 00 06 06 3D FF 00 0E 00 00 3C 6F 54 5B 6E 6C 00 61 21 05 05 00 00 1C F2 00 00 00 0F 69 64 61 4C 67 65 04 76 00 00 2A 01 00 10 B1 06 0A 02 0A 6E 65 62 6A 3B 01 00 61 02 01 B7 00 00 0B 00 00 00 00 00 69 01 6C 61 29 00 05 2F 00 00 00 00 46 A2 00 02 12 0B 03 74 00 65 76 56 0A 01 6C 03 06 01 00 00 00 00 00 00 00 3E 0F 01 61 01 53 00 61 00 00 B1 01 02 0E 01 07 0B 0C 01 4C 00 2F 00 75 05 6E 00 00 00 00 00 1B 00 00 00 07 00 69 04 6C 0A 6D 53 67 00 00 00 09 03 1C 07 04 15 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ...1........ ........<init>.. .()V...Code...Li neNumberTable... main...([Ljava/l ang/String;)V... SourceFile...Sum 10.java........S um10...java/lang /Object.!....... ................ .........*...... ................ ...........F.... .....<.=........ ‘<..‘=...... ................ ................ ............ Bytecode Eingaben Ausgaben läuft auf JVM läuft auf Prozessor 175 / 534 Java Quellcode-Datei: NumberOfDigits.java public class NumberOfDigits { public static void main (String [] args) { //"Zutaten" int n; int d; //"Zubereitung" n = Integer.parseInt(args[0]); d = 1; while(n>9) { n = n / 10; d = d + 1; } System.out.println(d); } } 176 / 534 Java Bytecode erstellen 1 Quelltext wird mit einem Editor bearbeitet 2 und in der Datei NumberOfDigits.java gespeichert 3 Erzeugen von ausführbarem Bytecode: C:\> javac | {z NumberOfDigits.java } Aufruf des Compilers | {z } dem Compiler sagen, welche Datei erzeugt die Datei NumberOfDigits.class 177 / 534 Java Bytecode-Datei: NumberOfDigits.class mit einem Hex-Editor betrachtet... 00000000h: 00000010h: 00000020h: 00000030h: 00000040h: 00000050h: 00000060h: 00000070h: 00000080h: 00000090h: 000000a0h: 000000b0h: 000000c0h: 000000d0h: 000000e0h: 000000f0h: 00000100h: 00000110h: 00000120h: 00000130h: 00000140h: 00000150h: 00000160h: 00000170h: 00000180h: 00000190h: 000001a0h: 000001b0h: 000001c0h: 000001d0h: 000001e0h: 000001f0h: CA 00 16 28 65 61 6E 6F 65 00 00 75 6A 01 65 00 72 61 01 74 69 07 21 08 05 00 00 00 1C 00 07 18 FE 10 07 29 4E 69 67 75 72 07 1C 6D 61 00 67 15 69 6E 00 53 6F 70 00 00 2A 01 00 02 04 00 00 00 BA 00 00 56 75 6E 2F 72 4F 00 00 62 76 11 65 28 6E 67 15 74 2F 72 05 01 B7 00 00 3C 60 01 09 0E BE 11 17 01 6D 01 53 63 66 08 1D 65 61 6A 72 4C 67 2F 4C 72 50 69 00 00 00 00 57 04 3D 00 00 00 00 09 01 00 62 00 74 65 44 07 07 72 2F 61 01 6A 3B 53 6A 65 72 6E 06 09 01 00 00 3D A7 0A 09 1B 00 00 00 04 65 16 72 46 69 00 00 4F 6C 76 00 61 29 79 61 61 69 74 00 00 B1 01 02 1B FF 00 00 00 00 12 06 43 72 28 69 69 67 18 1E 66 61 61 08 76 49 73 76 6D 6E 6C 00 00 00 00 00 10 F1 00 0B 0F 31 00 3C 6F 54 5B 6E 6C 69 0C 0C 44 6E 2F 70 61 01 74 61 3B 74 6E 00 00 00 09 03 09 B2 00 00 00 00 13 69 64 61 4C 67 65 74 00 00 69 67 6C 61 2F 00 65 2F 01 53 01 00 1D 00 00 00 A4 00 22 0F 22 21 0A 6E 65 62 6A 3B 01 73 19 1F 67 2F 61 72 6C 10 6D 69 00 74 00 00 00 01 0B 00 00 03 00 00 00 0A 00 69 01 6C 61 29 00 2E 00 00 69 4F 6E 73 61 6A 01 6F 13 72 04 02 01 00 00 00 0F 1C 08 0C 10 00 14 74 00 65 76 56 13 6A 1A 20 74 62 67 65 6E 61 00 2F 6A 65 28 00 00 0A 0C 23 1B B6 00 00 00 06 00 3E 0F 01 61 01 4E 61 07 01 73 6A 2F 49 67 76 03 50 61 61 49 01 01 00 00 2A 10 00 00 14 01 00 15 01 4C 00 2F 00 75 76 00 00 01 65 49 6E 2F 61 6F 72 76 6D 29 00 00 00 01 03 0A 04 00 00 00 0F 07 00 69 04 6C 0A 6D 61 1B 0E 00 63 6E 74 53 2F 75 69 61 01 56 07 00 00 00 32 6C B1 08 0D 0D 0A 00 03 6E 6D 61 53 62 0C 0C 4E 10 74 74 01 74 6C 74 6E 2F 00 00 00 00 06 09 B8 3C 00 00 00 00 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ...1.!...... ................ .......<init>... ()V...Code...Lin eNumberTable...m ain...([Ljava/la ng/String;)V...S ourceFile...Numb erOfDigits.java. ................ ........... ...N umberOfDigits... java/lang/Object ...java/lang/Int eger...parseInt. ..(Ljava/lang/St ring;)I...java/l ang/System...out ...Ljava/io/Prin tStream;...java/ io/PrintStream.. .println...(I)V. !............... ................ .*............ ................ ...W.......#*.2 ..<.=........l< ..‘=...... ........"....... ................ ........"....... 00000200h: 00 00 02 00 0E ; ..... 178 / 534 Java Bytecode: Auschnitt aus NumberOfDigits.class Befehl Nr 6: 7: 8: 9: 10: 12: 15: 16: 18: 19: 20: 21: 22: 23: 24: Befehl istore 1 iconst 1 istore 2 iload 1 bipush 9 if icmple 27 iload 1 bipush 10 idiv istore 1 iload 2 iconst 1 iadd istore 2 goto 9 Code des Befehls 3C 04 3D 1B 10 09 A4 00 0F 1B 10 0A 6C 3C 1C 04 60 3D A7 179 / 534 Übung: Beispiele aus der Vorlesung Die folgenden Beispiele (GGTDiff, SumN) wurden in der Vorlesung besprochen Es gibt je 2 Varianten Als Übung für Zuhause: Vergleichen Sie die Varianten Kopieren Sie den Quellcode in einen Editor, speichern Sie unter dem entsprechenden Namen, übersetzen Sie diese und führen Sie den Bytecode aus. 180 / 534 Berücksichtigung von falschen Eingaben import java.util.Scanner; public class GGTDiff { public static void main (String[] args) { int n = 0; int m = 0; boolean ok = true; Scanner reader = new Scanner(System.in); if (reader.hasNextInt()) { n = reader.nextInt(); if (reader.hasNextInt()) { m = reader.nextInt(); } else { ok = false; } } else { ok = false; } if (ok) { if (n == 0 || m == 0) { System.out.println(m+n); } else { while ( n != m ) { if ( m > n ) { m = m - n; } else { n = n - m; } } System.out.println(m); } } else { System.out.println("FALSCHE EINGABE"); } } } 181 / 534 Berücksichtigung von falschen Eingaben import java.util.Scanner; public class GGTDiff { public static void main (String[] args) { int n = 0; int m = 0; boolean ok = false; Scanner reader = new Scanner(System.in); if (reader.hasNextInt()) { n = reader.nextInt(); if (reader.hasNextInt()) { m = reader.nextInt(); ok = true; } } if (ok) { if (n == 0 || m == 0) { System.out.println(m+n); } else { while ( n != m ) { if ( m > n ) { m = m - n; } else { n = n - m; } } System.out.println(m); } } else { System.out.println("FALSCHE EINGABE"); } } } 182 / 534 Berücksichtigung von falschen Eingaben import java.util.Scanner; /* * Liest beliebig viele Ganzzahlen ein und gibt nach Ende * der Eingabe deren Summe aus. Falls eine nicht als * Ganzzahlen interpretierbare Zeichenkette eingegeben * werden wird, wird mit einer Fehlermeldung abgebrochen. */ public class SumN { public static void main (String[] args) { Scanner reader = new Scanner(System.in); boolean ok = true; int sum = 0; while (reader.hasNext() && ok) { if (reader.hasNextInt()) { sum += reader.nextInt(); } else ok = false; } if (ok) { System.out.println(sum); } else { System.out.println("FALSCHE EINGABE"); } } } 183 / 534 Berücksichtigung von falschen Eingaben import java.util.Scanner; /* * Liest beliebig viele Ganzzahlen ein und gibt nach Ende * der Eingabe deren Summe aus. Falls eine nicht als * Ganzzahlen interpretierbare Zeichenkette eingegeben * werden wird, wird mit einer Fehlermeldung abgebrochen. */ public class SumN { public static void main (String[] args) { Scanner reader = new Scanner(System.in); boolean ok = true; int sum = 0; while (reader.hasNext()) { if (reader.hasNextInt()) { sum += reader.nextInt(); } else { ok = false; break; //Schleife wird abgebrochen } } if (ok) { System.out.println(sum); } else { System.out.println("FALSCHE EINGABE"); } } } 184 / 534 Lektion 2, Teil 3: Klassen (1) 185 / 534 Klassen - eigene Datentypen definieren Wiederholung: Ein Datentyp bestimmt eine Menge von Werten und darauf anwendbare Operationen double int 17 -103 + - * / % ... 3 42 ... 1.6 0.17e2 3.1415 ... 0.0000003 + - * / % ... 186 / 534 Klassen - eigene Datentypen definieren Wir haben bisher folgende Datentypen verwendet: I I I I int double char String 187 / 534 Klassen - eigene Datentypen definieren Wir wollen lernen, eigene komplexere ”Datentypen” selbst zu erstellen Rational 1 2 3 3 5 ... 4 188 / 534 Klassen - Beispiel Rational Datentyp für Brüche (Bezeichnung Rational ist selbst gewählt) ist zusammengesetzt aus 2 Zahlenwerten: ganzzahliger Zähler (Numerator) ganzzahliger Nenner (Denominator) Beispiele: Mögliche ”Werte” für Rational: 3 4 1 9 ← Numerator ← Denominator 189 / 534 Klassen - Beispiel Rational Die (minimale) Definition unseres neuen Datentyps erfolgt zunächst durch class Rational { int num; int denom; } //Zaehler //Nenner Das bedeutet: Der neue Typ Rational besteht aus 2 ganzzahligen Komponenten: num und denom num und denom sind Namen von Datenelementen (manchmal auch Instanzvariablen oder Felder genannt) 190 / 534 Klassen - Beispiel Rational class Rational { int num; ⇐ Variablendefinition Klassendefinition int denom; ⇐ Variablendefinition } Eine Klassendefinition ist wie ein Bauplan Die Datenelemente werden mit Variablendefinitionen festgelegt 191 / 534 Klassendefinition allgemein class Identifier { Variabledefinitions(Datenelemente) Klassendefinition ... } Eine Klassendefinition ist wie ein Bauplan Die Datenelemente werden mit Variablendefinitionen festgelegt 192 / 534 Klassen - eigene Datentypen definieren Weitere Beispiele von Typen mit 2 oder mehreren Komponenten (aus den Übungsrunden): AsciiImage ============,.V+.;============ ===========;.X##..;=========== ===========..####..=========== ==========,.##M###.:========== =========;.R##WW##=.;========= =========..##MWMW##,.========= ========:.I##WWMWW#W.,======== =======;.:##WWWWWW##I.;======= =======:.W########M##..======= =======.:############V.;====== =======.####...,.,M###,.====== ======,.###:..+++;,B..#.;===== =====;.#;.#i+YXVVY:#V.#..:==== ====:..#..##.RYYIt##...#=.,=== ==;..+#;...#######W....##W..:= :..t###......iVV=....,.+#iM#.. .B#i,#..,,..........,,..#,..#I V#...#..,,,,,.,,,,:,,,..R#..V# ;#+.i#..,,,,,,,,,.,,,,,.iX.X#, .i#=MV..,,,,.,,,,,,.,,,..###.. ,.t##..,,,,,,,,,,,,,,:,..V##.; ..M#M..,,,,.,.,,,,,,,:,,.=##.. i###M..,...........,,:,,..###. .####........=II;.....,,.;##R. ,...#....X####MW###B.....Wi..: ==;,##,###;........##i...#;,== ,::::::,,,,,,,,,,,,,,,,,,::::::::,,,,::;::::::,,:,,,,,,,,,,,,:,,,,,,,,:,,,,,,,,,,,,,,.,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,::,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...,,...,,,,..... ,,,....,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,:,,:=+ittIIIItti+=:,,,,,.,..,,,,,,,,,,,,,,............,...... ,.,,...,,,....,...........,..,...,..,..;+tIItIYYYYYYYYYIIIIi;,......,,,,,,,......................... ,,........................,..........:iIIIItiIIIIIYYYYYYYYYYIt=.........,,.......................... ....................................;IIti+=;;=++itIYYYYYYYYYYYYt:................................... ,..................................;Ii;,........,:;iIIYYYYYYYYYYI=.................................. ..................................=Ii:............,:+tIYYYYYYYYYYI=................................. .................................;II=,.............:;+tIYYYYYYYYYYI:................................ ................................;iIt;.............,,:;=itIYYYYYYYYYt,:,...,......................... ,:::,,::.......................;tIY+,................,,:=IYYYYYYYYYY+;;::::,..,.,................... ;;==;::::,,,,,,,,,,,..........,=IYY+,.........,::,,,,:;=+IYYYYYYYYYYt=+=;;::::,,:................... +++==:;;:::;;:;=;;;:::,.......=itIIt+====;..,+ti==+itIItiIYYYYYYYYYYIii+++;;;;;;;,,..............,,, ++==;;;;;;;=;;==+==:;=,...,...;IIYY+=;,=+;,.:i=:.;+++=;:;iYYYYYYYYYYYiiiii+====+=;:.............,,.. +++=====;=====i+++++=i=:;+=+;:+IIYI;...,,...,;:....,...,;tYYYYYYYYYYYttiii+=++++==;,...........,,,.. iii++++==++++iii+iiiitiiii+tiittYYY=........,,,.......,;+IYYYYYYYYYYYt+++++++++ii++;,..........,,,,, tItiitttiii+++i+iitttttttttIIIIIIIYi,.......,:,......,;+tYYYYYYYYYYYYt+++;;;;;;;;::::,....,,,,,,,,,: ttttiiitttttii+++iiititttttIIYYYIYYI;,...,.,=+=....,:;+tIYYYYYYYYYYYYYIIIIttttiiii+=;::::;=;+i+;=+=+ tIIttiiittttttti+ittttttttIIIYYYYYYYi;:,..:iti=,,,,:;=itIYYYYYYYYYYYYYIIIIttttttttttiii+=+=+iittttii tIIttiittttttttittttIItIIItIIIYYIIYYI;,:;,,:=+++;:,,;=itIYYYYYYYYYYYYYItIttttttItttttii++==+ittttttt tIttttttttttttttttttIttttttttIIYIYYYYt=,..,:;=;::::;=itIYYYYYYYYYYYYYYItttttttttttttii+++iiitttttttt ttttttttttttIIItttttiiiiiii++tIIYYYYYYIi;....,::;;=itIIIYYYYYYYYYYYYYYIiitttiiiitttttttttttttiiiitii ttttttttttttttIIIIItttttiiii+tIIYIYYIYYYI+:.,:;=ittIIIIYYYYYYYYYYYYYYYItiiii=+++ttttiiiiiiiiitttttii tttitttIttttttttttttitiii+==;=IIIYYYYYYYYYYIIIIIIIIIIIIIIYYYYYYYYYYYYYYttttttiiitttttttttttii+++itii ttttIttIItttiiiiiii+++========iIYYYYYYYYYYYYtitIIIIIIIIIttIYYYYYYYYYYYYIttiiiii+ittttttttttttittiiii ttttIIIItttii++++=====+======++tYYYYYYYYYYYYi:;=iitttii+++iIIYYYYYYYYYYItii+==++iiiiiiiiiiiiiittti++ tttttttiiii++iii+iii+=+=+==+=iiIYYYYYYYYYYYIt:,::;====;;;;=+IYYYYYYIIYYYItti+ii++=;;;+=;;;;;=++iii+= ttttiiii++++=iitit+tIttittitItIYYYIIIYYYYIt+;:,,,,,,,,,,,,:;iIIIIIIIIYYYIIIIIttttiitt+;,:;;++=+ittti Ittttttiii++ittiitiiIIIIIItIIIIIIIIIYYIt=;,................,;tIIItIIIYYIIIIttttii++++=;,:=i=+;=itti+ ttttttttiiiiiii++iiIIIttIItIIIIIIYIIIi;,...................,=IIIt+ttIIIIIIIItii=:,.,,:::====++ittiii tttttItiitiii+i=+ttItIttIItIIIYYYYIIi:......................;tittiIIYIIIIIIIIItti;,,,,:::;==+===+iii ttttittt=======++tttttttIttIIIYIIIti:......................,;ttttiIIIIIIttIIIIIti++;=:;::=;;:;;++++i tttttttI++;::;;=;+iitiitIIIYYYYIt+=;.......................,=+ittiIIItti+iittIIIIti+=;::,:,,,,::::=i ttttttttttti+;:;===iiittIIYIIYIt=:,........................,=+itti+=;;;:;;=+itIIIIIItttt+==+=::,,::: iiiiiitttttttt+=++=;=iIYYIIIIII+,..........................:;==+==;:,::=+ittIIIIIIIIIIttttttii+=;::, tttttttiiiitiii+++=;+IIIYIIYIIIt;..........................,;==;;==ittIIIIIIIIIIIIIIIIItttIttt+=:.., iiii+++==;===;;;==iIIIIIYIIIIItii=:,.....................,:;+ittIIIIIIIIIIIIIIIIIIIIIIIIItttttttii+= ii+===;+=++=iiiitIIIIIIIIIIIIIttttii+++=:,.............,=++iIIIIIIIIIIIIIIIIIIIIIIIIIIIIItii+itttiit i++=+========++iIIIIIIIIIIIIIttttIttttii++++===;;;;:;==+itttIIIIIIIIItIIIIIIYIIYIIYIIIIIIIttiittti+t ..........;IWYI+MI;,,,,,,,,, ......,.+.,#B:.#t...,Y,,,,,, ....:....VR#t.+t.,.I;.I+,,,, ...;...;:+V#:V#I=:;.,=+tX,,, ..+.......i#W.#XIi+ii=:,tI,, .,,......,XWW.Bt:;:+IYi+XR=, .I......:=R##,Wt.:IItt+I+IB, .+.......=RM#.XV,=:;=+IXXR#= ;....,.:,;IM#.+R,+itii:+iYWY i......,.;YMB.Mi...;..;=:tMV +.::;=;i+iVMRtW;.:=+.+==;iWY i.,,,;;iiiIMB:Y=+tItiIVVRVWV YIiiII:+:,tBBt.:.:,:;IttYR#; Y:.,;=:i:IYBMt.=.;=YYYIYIX#, I..=ti+i;iRWM;Xt:iIYtVVVVWW, I+.ii,,,=YBW#=V.,:+i=ttYB#;, .i.::.:+tRM#B.V.;;IYYVVBW#,, .X=,::;+iBWWt.#=YIXXXVBW#,,, ..MY;;=IIXB#V.#iIVVYXM##i,,, ..:X,=+iYVW#X+MXBMMBW##t,,,, ....WXIYRM##tBBVVMM##M+,,,,, .....I#######MMB###MY+,,,,,, ........+RMRVtYMBXYIt:,,,,,, .........,,,,,,,:;=;,,,,,,,, Complex 1 + 3i -5 - 1.1i 2 - 3i ... 193 / 534 Klassen - Beispiel Rational Wie können Klassen benutzt werden? Wie spezielle, selbst definierte Typen... Aber wie wird ein neuer ”Wert” erzeugt und zugewiesen? Beispiel (Verwendung von Klassen) primitiver Typ neuer Typ (Klasse) double temperature; temperature = 12.5; Rational r; r = ...? 194 / 534 Klassen - Beispiel Rational Klassen sind wie Baupläne Nach diesem Bauplan können zur Ausführungszeit des Programms Objekte dieser Klasse erzeugt werden Objekte heißen manchmal auch Exemplare oder Instanzen der Klasse Objekte belegen Speicherplatz zur Laufzeit des Programms 195 / 534 Klassen - Beispiel Rational Klassen definieren Referenztypen class Rational Variablen eines solchen Typs und der Speicherplatz des referenzierten Objekts existieren getrennt voneinander Rational bruch; bruch = new Rational(); bruch.num = 3; bruch.denom = 4; int num int denom 3 4 num denom bruch 196 / 534 Unterschied ”primitive” Variablen - Referenzvariablen Variablen eines primitiven Typs: Referenzvariablen sind Variablen der ”Objekt-Typen” (Klassen): int String double Rational (siehe oben) char ... int answer = 42; Rational bruch; bruch = new Rational(); bruch.num = 3; bruch.denom = 4; 42 answer 3 4 num denom bruch 197 / 534 Unterschied ”primitive” Variablen - Referenzvariablen Variablen eines primitiven Typs speichern Werte Referenzvariablen verweisen auf Objekte int answer; Rational bruch; 42 answer 3 4 num denom bruch 198 / 534 Datenelemente - Zugriff Die Datenelemente eines Objektes können einzeln angesprochen werden Syntax: ObjectvariableIdentifier.ElementIdentifier Werden genauso gehandhabt wie lokale Variablen des gleichen Typs Rational r = new Rational(); r.num = 1; r.denom = 3; r.num++; r.denom *= 2; double rationalValue = (double) r.num / r.denom; System.out.println("Der Wert des Bruches " + r.num + "/" + r.denom + " ist " + rationalValue); 199 / 534 Referenztypen Rational r = new Rational(); r.num = 1; r.denom = 2; Rational s = new Rational(); s.num = 3; s.denom = 4; Objekt r 1 denom 2 num Objekt s 3 denom 4 num 200 / 534 Unterschied ”primitive” Variablen - Referenzvariablen primitive Variable: Hier wird der Wert von a in b gespeichert (kopiert)... int a = 21; int b = a; 21 a 21 b 201 / 534 Unterschied ”primitive” Variablen - Referenzvariablen Referenzvariable: Beide Variablen verweisen hier auf dasselbe Objekt... (es wird hier keine Kopie erzeugt) Rational r = new Rational(); r.num = 1; r.denom = 2; Rational s = r; r 1 num 2 denom s 202 / 534 Referenztypen Hier wird eine echte Kopie eines Objektes erzeugt. Das Resultat sind Objekte, die gleich sind aber nicht identisch... Rational r = new Rational(); r.num = 1; r.denom = 2; Rational s = new Rational(); s.num = r.num; s.denom = r.denom; Objekt r 1 denom 2 num Objekt s 1 denom 2 num 203 / 534 Objekt-Identitätsprinzip Jedes Objekt ist per Definition unabhängig von seinen konkreten Attributwerten (=Werte der Datenelemente) von allen anderen Objekten eindeutig zu unterscheiden 204 / 534 Unterschied ”primitive” Variablen - Referenzvariablen int a = 1; int b = a; b = 2; System.out.println("Wert von a: " + a); Ausgabe: Wert von a: 1 205 / 534 Unterschied ”primitive” Variablen - Referenzvariablen Rational r = new Rational(); r.num = 1; r.denom = 3; Rational s = r; s.num = 2; System.out.println("Bruch r: " + r.num + "/" + r.denom); Welche Ausgabe ist hier zu erwarten? 1 Bruch r: 1/3 2 Bruch r: 2/3 X ”Aliasing” 206 / 534 null-Referenz Wenn eine Referenzvariable kein Objekt referenzieren soll kann man ihr null zuweisen (null-Literal) null ist nicht zu verwechseln mit einer fehlenden Initialisierung! Rational r; //Fehler: Zugriff ohne Initialisierung if (r == null) { ... } r r = null; if (r == null) System.out.println("kein Objekt"); 207 / 534 Datenelemente: Gültigkeitsbereich und Lebensdauer Ein Datenelement ist innerhalb der Klasse gültig, in der es definiert wurde Die Reihenfolge der Definition in der Klasse spielt keine Rolle Die Lebensdauer entspricht der Lebensdauer des Objektes I I Beginn: Erzeugung mit new Ende: Wenn keine Referenzvariable mehr auf das Objekt verweist (z.B. wenn man im obigen Beispiel r und s ein neues Objekt oder null zuweist) 208 / 534 Objekte In der realen Welt vorkommenden Gegenstände können durch Objekte modelliert werden Beispiele für Objekte: Lampe, Telefon, Fahrrad, Mensch, Versicherungspolizze Objekte können charakterisiert werden durch: I I I Zustand Verhalten Identität Kapsel mit eigenem Zustand+Verhalten+Identität 209 / 534 Klassen Eine Klasse beschreibt die Struktur und das Verhalten einer Menge gleichartiger Objekte fasst Attribute (Datenelemente) und Operationen (Methoden) zu einer Einheit zusammen. Attribute (Datenelemente): beschreiben Zustand Operationen (Methoden): beschreiben Verhalten 210 / 534 Objekt-Klassen-Prinzip Ein Objekt ist eine zur Ausführungszeit vorhandene Instanz (ein Exemplar), die I I für ihre Datenelemente Speicherplatz allokiert sich entsprechend dem Protokoll ihrer Klasse verhält 211 / 534 Klassen class Bicycle { // Datenelemente int speed = 0; int gear = 1; // Methoden void speedUp() { speed = speed + 5; } void applyBrakes() { speed = speed - 5; } void changeGear(int newValue) { gear = newValue; } void printStates() { System.out.println("Geschwindigkeit:" + speed + " Gang:" + gear); } } 212 / 534 Hauptprogramm (benutzt Klasse Bicycle) class BicycleApplication { public static void main(String[] args) { // Erzeuge zwei Bicycle Objekte Bicycle bike1 = new Bicycle(); Bicycle bike2 = new Bicycle(); // Methoden der Objekte werden aufgerufen bike1.speedUp(); bike1.speedUp(); bike1.changeGear(2); bike1.printStates(); bike2.speedUp(); bike2.changeGear(2); bike2.speedUp(); bike2.changeGear(3); bike2.printStates(); } } 213 / 534 Methoden Eine Klassendefinition besteht aus der Definition von Datenelementen: Welche Daten sollen Objekte beschreiben speichern Zustand der Objekte Methoden: Welche Aktionen können Objekte auf den Daten durchführen - steuern Verhalten der Objekte class Rational { //Datenelemente int num; int denom; //Methode: Ausgabe am Bildschirm void output() { System.out.println(num + "/" + denom); } } 214 / 534 Aufruf einer Methode Der Aufruf einer Methode ähnelt dem Zugriff auf die Datenelemente Syntax: ObjectvariableIdentifier.MethodIdentifier() Rational r = new Rational(); r.num = 4; r.denom = 6; r.output(); erzeugt am Bildschirm 4/6 215 / 534 Methoden Hauptprogramm Klassendefinition class Main { public static void main (String[] args) { //Zutaten Rational r = new Rational(); class Rational { //Datenelemente int num; int denom; //Zubereitung r.num = 4; r.denom = 6; r.output(); r.num = 3; r.output(); } //Methode: Ausgabe am Bildschirm void output() { System.out.println(num + "/" + denom); } } } 216 / 534 Methoden: Call Sequence 1 Das aufrufende Programm Main.java wird unterbrochen 2 Der Methodenrumpf wird durchlaufen 3 Das aufrufende Programm wird fortgesetzt Hauptprogramm Klassendefinition Main.java Rational.java class Main { public static void main (String[] args) { //Zutaten Rational r = new Rational(); } //Zubereitung r.num = 4; r.denom = 6; r.output(); 1 r.num = 3; r.output(); 3 4 class Rational { //Datenelemente int num; int denom; //Methode: Ausgabe am Bildschirm void output() { System.out.println(num + "/" + denom); } 2 } } 217 / 534 Aufbau einer Methode Der Aufbau eines Methodenrumpfs ist so, wie wir es von main gewohnt sind und enthält I I I Definitionen von lokalen Variablen Zuweisungen Kontrollanweisungen Die lokalen Variablen werden bei jedem Aufruf der Methode neu erzeugt und beim Verlassen wieder verworfen 218 / 534 Aufbau einer Methode Jedes Java-Programm ist eine Klassendefinition Jede Methode ist Komponente einer Klasse in den bisher verwendeten ”Programmrahmen” haben wir immer eine Methode main benutzt Diese war Komponente einer ausführbaren Klasse (”entry-point”) Klassen ohne Methode main können nicht direkt ausgeführt werden, sondern definieren Referenztypen die von anderen Klassen benutzt werden können (mit new) 219 / 534