Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Teil V STRUKTURIERTES Elementare Sprachkonzepte in Java PROGRAMMIEREN Vorlesung im Sommersemester 2014 Prof. E.G. Schukat-Talamazzini Stand: 15. Oktober 2014 Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Hello World! Hello World! Das kleinstmögliche Programm in der Sprache Java [’d`a:v] Aufruf mit Kommandozeilenparametern Funktionen Programmquelldatei ’Hello.java’ Programmquelldatei ’Hello.java’ class Hello { public static void main (String[] arx) { System.out.println ("Hello World!"); } } class Hello { public static void main (String[] arx) { System.out.println ("Strukturiertes" + ’ ’ + "Programmieren" + arx[0]); } } Übersetzungsaufruf $ javac Hello.java Bytecodeausführung $ Übersetzung und Ausführung $ $ javac Hello.java java Hello " ist voll der Bringer." java Hello [.class] Bildschirmausgabe Hello World! Bildschirmausgabe Strukturiertes Programmieren ist voll der Bringer. Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Funktionen Σ Hello World! Warum ist das in Java komplizierter als in anderen Sprachen? Lexikalische Ebene: Literale und Variablennamen Programmsyntax Einfache Typen, Operatoren und Ausdrücke Ein Java-Programmtext ist eine Menge von Klassendeklarationen. • Eine dieser Klassen besitzt den Führungsanspruch. Typsicherheit und Typkonversion • Sie beinhaltet die öffentliche Klassenmethode Anweisungen, Blockstruktur und Kontrollfluß public static void main (String[] arx) { ... } ohne Rückgabewert, aber mit den Zeichenreihenobjekten arx[0] , arx[1] , arx[2] , Referenzen und Felder ... ... ... Definition und Aufruf von Funktionen und Prozeduren für die Programmaufrufargumente. Zusammenfassung Programmausführung Ausführung von main() mit aktuellen Kommandozeilenargumenten Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Namen, Bezeichner, Identifikatoren Lexikalische Einheiten Die kleinsten („terminalen“) Einheiten einer Programmiersprache • Namen für Variablen, Funktionen, Typen (benutzerdefiniert) • Operatoren & Schlüsselwörter für Typen, Kontrolle, Deklaration (vordefiniert) (Buchstaben / Sonderzeichen) • Literale für Zahlen, Zeichen, Zeichenketten (alphanumerisch & Sonderzeichen) Benutzerdeklarierte Namen Alle nicht reservierten Wörter der folgenden Gestalt: name alphanum digit letter ::= letter {alphanum}∗ ::= letter | digit ::= [0|1|2|3|4|5|6|7|8|9] ::= „Unicode-Standard“ Typsicherheit Anweisungen Felder Reservierte Wörter Folgende 61 Wörter sind für Benutzerdefinitionen tabu: abstract assert◦◦ case cast◦ continue default extends false ◦ future generic◦ ◦ inner instanceof new null protected public strictfp◦◦ super throws transient while ◦ ◦◦ boolean break catch char do double final finally ◦ goto if int interface ◦ operator outer◦ rest◦ return switch synchronized true try Wörter sind zwar reserviert, werden aber nicht benutzt Reservierte Wörter, aber erst seit Java-Version 1.2 byte class else float implements long package short this void byvalue◦ const◦ enum◦◦ for import native private static throw volatile Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Typsicherheit Namenskonventionen Anweisungen Felder Funktionen Σ Literale Eigennamen für Wertebereichselemente eingebauter Datentypen Etikette benutzerseitiger Namensvergabe 8 Elementare Datentypen Unverbindliche Regelung — breite Akzeptanz • Klassennamen Anfanggross boolean char byte short int long float double String, Vector, Rectangle, ... • Konstantennamen MAJUSKELN PI, MAX_FLOAT, INFINITY, ... • Variablennamen minuskeln i, x, lfdnr, f6, ernte23, b88, ... • Methodennamen binnenMajuskeln add, move, setValueToZero, gotoAldi, ... Wahrheitswert true oder false 16-bit Unicode 2.0 Zeichenvorrat 8-bit 16-bit 32-bit 64-bit Ganzzahl Ganzzahl Ganzzahl Ganzzahl 32-bit 64-bit IEEE 754-1985 Gleitkommazahl IEEE 754-1985 Gleitkommazahl in in in in Zweierkomplementdarstellung Zweierkomplementdarstellung Zweierkomplementdarstellung Zweierkomplementdarstellung Vergabe „sprechender“ Eigennamen Referenztypen für Klassen und Felder Typisch für Java: ArrayIndexOutOfBoundsException Ausnahme sind kurzlebige Hilfsvariable wie i, r Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Das Literal null steht für den undefinierten Verweis. Funktionen Σ Bezeichner Ausdrücke Literale für ganzzahlige Typen Syntax ganzzahliger Literale Oktalzahlen Darstellung von int- und long-Werten: intlit ::= {−|+} digit + Führende Nullen signalisieren Oktaldarstellung. longlit ::= intlit [L|l] Beispiele 007, -04L aber nicht: 0815 Es gibt keine Literale für short und byte. Beispiele Mindestens eine Ziffer ist geboten: 4711, -17, 3l, 0L Typsicherheit Anweisungen Felder Funktionen Literale für Gleitkommatypen Syntax von Gleitkommaliteralen Darstellung von float- und double-Werten: doublit ::= {−|+} mantissa {exponent} mantissa ::= [digit + . digit ∗ ] | [digit ∗ . digit + ] | digit + exponent ::= [E|e] intlit floatlit ::= doublit [F|f] intlit ::= {−|+} digit + Hexadezimalzahlen Führendes 0x signalisiert Hexadezimaldarstellung. • Überflüssig, aber erlaubt: +883 Beispiele • Verwechslungsgefahr 911 versus 91l 0x32, 0x5b, 0xFABEL aber nicht: 0XL Beispiele 3.14, -17., +.4, -00.00, 1.8e+7, 1.E+7f, ... • d|D für double-Literale überflüssig, aber erlaubt • nur dezimale Mantissen: =β [017.0] = 17 und 0x47.11 Syntaxfehler Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Literale für Zeichen symbol Darstellung von Unicodezeichen (Typ char) Nichtterminal bezeichnet Menge aller druckbaren Zeichen charlit ::= symchar | unichar | escape 0 unichar ::= 0 unihex 0 symbol \u unihex 0 • Reserviert geeigneten Speicherplatz (Compiler) • Definiert unter Umständen den Startwert der Variablen 0 Spezielle nicht druckbare oder „belastete“ Zeichen \b \u0008 \t \u0009 \n \u000a \f \u000c \r \u000d \” \u0022 \’ \u0027 \\ \u005c backspace tabulator newline pagefeed carriage return double quote single quote backslash Typsicherheit Anweisungen Felder Funktionen Σ Deklaration Definition Name und Typ Name, Typ und Anfangswert int lfdnr; long i,j,k; float länge; double x1, x2; short jahr; byte day, month; boolean married; char ch, linefeed; int lfdnr=4711; long i=8L, j=16L, k=-32L; float länge=3.14124f; double x1=8.15, x2=22.5e+9; short jahr=1066; byte day=7, month=12; boolean pope=true, married=false; char ch=’\uAFFE’, linefeed=’\n’; Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Komplexe Datentypen Vordefiniert: Felder, Strings, Hüllklassen Lexikalische Ebene: Literale und Variablennamen Zeichenketten Hüllklassen Klasse String für die acht elementaren Typen: Einfache Typen, Operatoren und Ausdrücke Syntax des Stringliterals Boolean Character Byte Short Integer Long Float Double Typsicherheit und Typkonversion strlit ::= 00 charlit ∗ 00 Beispiele ”08/15” ”RTL 2” Σ 0 \ [b|t|n|f|r|00 |0 |\] Ausdrücke Funktionen • Vereinbart Name und Typ der Variablen Fluchtliterale Bezeichner Felder Lebenswichtige Informationen für Übersetzer oder Interpreter: ::= [0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|a|b|c|d|e|f]4 escape ::= Anweisungen Programmvariable sind vor erster Verwendung zu deklarieren! Syntax von Zeichenliteralen ::= Typsicherheit Variablendeklaration für elementare Typen Druckbare Zeichen · Fluchtliterale · Unicode16 symchar Ausdrücke ”Ende\n” ”say \”Hello!\”” Konversion Grundtyp Referenzen und Felder Zeichenreihe Die vier Zahltypen lassen sich in ein Stringobjekt konvertieren, z.B.: String str = String.valueOf (3.14F); Konversion Zeichenreihe Anweisungen, Blockstruktur und Kontrollfluß Grundtyp Stringobjekte werden mit Hüllklassenmethoden umgeformt, z.B.: float x = Float.parseFloat (str); Definition und Aufruf von Funktionen und Prozeduren Zusammenfassung Funktionen Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Typsicherheit Arithmetik elementarer Zahltypen 8 16 32 64 16 float double +127 +32 767 +2 147 483 647 +9 223 372 036 854 775 807 +65 535 \uffff −45 38 ±1.4 · 10 ±4.9 · 10−324 unär binär logisch ! &, |, ˆ &&, || ±3.402 823 5 · 10 ±1. 797 693 134 862 315 7 · 10308 Beschränkter Wertebereich Beispiel Im Zahlbereich wird ringförmig gerechnet. Wenn = [n] = 231 − 1, dann = [n+1] = −231 . Ganzzahlige Division Bei Division wird zur Null hin gerundet. <, <=, == >, >=, != Bitmuster ˜ &, |, ˆ <<, >>, >>> = Ganzzahliger Rest Beispiel Für die Restberechnung gilt das Axiom 3%2 ≡ 1 und (−3)%2 ≡ −1 und sogar 3%(−2) ≡ 1 =β [(x/y) ∗ y + x%y] = =β [x] ?: Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Arithmetik mit Gleitkommazahlen Typsicherheit Überlauf Unterlauf und Überlauf Division erfolgt reellwertig Restbildung gemäß Axiom Alle Operationen sind strikt +∞ (pos), −∞ (neg) Es gibt zwei Nullen: =β [x ∗ 0] = ⊥ Unterlauf +0.0 (pos), −0.0 (neg) Undefiniert ⊥ (NaN = not a number) Anweisungen =β [+0.0] 6= =β [−0.0] Kürzungsregeln scheitern: =β [0.0 ∗ (1.0/0.0)] = ⊥ Funktionen IEEE 754 Standard Verbietet bei einer längeren Abfolge von Gleitkommaoperationen, auf die schrittweise anfallenden Mantissennormierungen zu verzichten und stattdessen mit breiteren ALU-Registern zu arbeiten. Java JIT-Compiler Die Arithmetik der Ausnahmewerte Auswertung von Gleitkommatermen bricht x y x+y x-y endlich ±0.0 x x endlich ±∞ ±∞ ∓∞ ±0.0 ±0.0 0.0 0.0 ±∞ endlich ±∞ ±∞ ±∞ ±∞ ∞/NaN ∞/NaN Felder Arithmetik mit Gleitkommazahlen Gleitkommaoperationen =β [x] = ⊥ 3/2 ≡ 1 und (−3)/2 ≡ −1 etcetera ternär Bezeichner Beispiel =β [(−x)/y] = −=β [x/y] = =β [x/(−y)] Vergleich Σ Es wird immer mindestens in int gerechnet. Typ char verhält sich wie vorzeichenloses short. Typen byte und short dienen nur der Speicherersparnis. Operatoren für elementare Typen arithmetisch +, -, ++, -+, *, /, % Funktionen Fünf Ganzzahltypen -128 -32 768 -2 147 483 648 -9 223 372 036 854 775 808 0 \u0000 32 64 Felder Ganzzahlige Arithmetik Wertebereiche elementarer Zahltypen in Java byte short int long char Anweisungen grundsätzlich nicht ab. x*y x/y x%y 0.0 ±∞ NaN ±∞ ±0.0 x 0.0 NaN NaN ±∞ ±∞ NaN ±∞ NaN NaN Hüllklassen Float.isInfinite(type) testet auf ±∞ Float.isNaN(type) testet auf ⊥ Rechenzeitersparnis durch Verzicht auf Zwischennormierung Hilfreiche Konstanten IEEE-754 Garantie =β [1F/0F] =β [1F/ − 0F] Nur noch für Klassen und Methoden mit = =β [Float.NEGATIVE_INFINITY] strictfp-Zusatz! = =β [Float.POSITIVE_INFINITY] Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Zuweisungsoperator Typsicherheit Anweisungen Felder Funktionen Σ Beispiele — Zuweisungsausdrücke Verknüpfungsoperator mit Nebenwirkung Zuweisungsausdruck L-value Zu unterscheiden von der Zuweisung selbst! zuweisungsfähig besitzt Adresse assignexpr ::= lexpr = expr denselben Typ. β 0 = β[=β [E ] /x] • Wirkung Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen =β [x=((y=1)+5)] = =β [(y=1)+5] = =β [(y=1)]+5 = =β [1]+5 = 6 und Wirkung β 0 = β[1/y , 6/x]. Σ Bezeichner Inkrement/Dekrement erhöhen vermindern Wert um Eins erst zuweisen, dann auswerten ±E , erst auswerten, dann zuweisen Syntaktisch inkorrekt int k=5, n,m; n = (k++); m = (++n); m += n+k; 17 -= 4 und PI /= 2 Funktionen E1 ◦ E2 , x ◦ = E2 , x ±± , ±± x Semantik Postfixform Beispiel Felder Beide Operandenausdrücke besitzen (im Prinzip) denselben Typ. Der Linksoperand x besitzt eine Adresse. Präfixform a[ggt(n,m)] += 1 Anweisungen Für die Operatoren ◦ ∈ {+, −, ∗, /, %} sind erlaubt: n++, k-- Effizienzvorteil Typsicherheit Syntax ++n, --k Äquivalent zu den Dreiadreßformen k = k * 5 x = x / (17+4) Ausdrücke Wirkungsweise arithmetischer Operatoren Syntaktischer Zucker & semantisches Kerosin Resultat zweistelliger Verknüpfung an ersten Operanden zuweisen: k *= 5 x /= (17+4) x oder a[5] oder a[i+3] Der Ausdruck x=(y=1)+5 ist semantisch gleichwertig mit x=((y=1)+5) („Klammerersparnisregel“ für =) und es folgen Wert Zwei- und Einadreßverknüpfungen In-place Arithmetik Linkswerte (β 0 = β[21/x]) . Geschachtelte Zuweisungsausdrücke Literale Konstante Nichtelementare Ausdrücke =β [x = E ] = =β [E ] • Wert 47.11f, Float.MAX_VALUE, x/y oder a[i]+3 β 0 (x) = =β [17+4] = 21 Gegenbeispiele • Der linke Ausdruck besitzt eine Adresse. Die Ausdrücke x=21 und x=17+4 haben den Wert und bewirken die punktweise Belegungsveränderung Wertvariable Referenzvariable Feldelement Objektkomponente • Beide Operandenausdrücke besitzen Kein L-Wert =β [x=17+4] = =β [17+4] = 21 Beispiele Für einen Zuweisungsausdruck x = E gilt: Wert und Nebenwirkung • Wert =β [±E ] =β [E1 ◦ E2 ] = ±=β [E ] =β [x ◦ = E2 ] =β [E ±±] = =β [x] ˜ ◦ =β [E2 ] =β [±± E ] // // // // Kommentar: =β [n] = 5 =β [m] = 6 =β [m] = 6 + 6 + 6 = =β [E1 ] ˜ ◦ =β [E2 ] = =β [E ] = =β [E ] ± 1 • Wirkung β 0 = β[=β [x◦E2/] x ] bzw. β 0 = β[=β [x]±1/x ] Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Boolesche Ausdrücke Felder Funktionen Σ Wahrheitswerttabelle ::= true | false | id ::= expr [== |! = | < | <= | >= | >] expr ::= boolexpr boolop2 boolexpr ::= Anweisungen Boolesche Verknüpfungen Syntax von Ausdrücken des Typs boolean boolexpr Typsicherheit ! boolexpr | (boolexpr ) Bezeichner vom Typ boolean; Vergleichsausdrücke kompatibel und ggf. geordnet. Operandenwerte AND OR XOR NEG x O O L L x&y O O O L x|y O L L L xˆy O L L O !x L L O O y O L O L lazy evaluation x&&y O O O L x||y O L L L George Boole 1815–64 Beispiele Vergleichsoperatoren Verwechslungsgefahr (==/=) Ordnungsrelation für Zahltypen! Gleichheit für Referenztypen? Für eine boolesche Variable a mit =β [a] = O gilt: ◦:M×M→B Bezeichner Ausdrücke Typsicherheit =β [a == true] = O =β [a = true] = L Anweisungen Felder Funktionen Wir schreiben z.B. ((a&b)|c) oder (a&b|c) oder (a&&b||c) für die entsprechenden Wahrheitswertverknüpfungen. =β [true] =β [x] gerade =β [x%2==0] = =β [false] =β [x] ungerade Σ Bezeichner =β [false] = =β [((a>=b) | (a<=b)) & (a != a)] Ausdrücke Typsicherheit Verzögert auswertendes AND/OR Semantik strikter und bedingter Auswertung (Ausnutzung dominanter Situationen L ∨ b = L und O ∧ b = O) =β [B1 |B2 ] = =β [B1 ] ∨ =β [B2 ] =β [B1 &B2 ] = =β [B1 ] ∧ =β [B2 ] =β [B1 ||B2 ] = =β [B1 &&B2 ] = L =β [B2 ] =β [B1 ] = L =β [B1 ] = O O =β [B2 ] =β [B1 ] = O =β [B1 ] = L Anweisungen • Nebenwirkungen Komponentenweise logische Verknüpfung Alle Ganzzahltypen (incl. char) Operandenwerte x 1010 y 1100 AND OR XOR x&y 1000 x|y 1110 xˆy 0110 Negation ˜x 0101 • Terminierungsverhalten (1+1==3) && (sqrt(-1)>0) ˜y 0011 Maskierung von Bitpositionen Man verwendet Masken, um aus einer Variablen nur bestimmte Bitpositionen herauszufiltern und den Rest auszublenden. • die beiden niedrigsten Bits aus m • Zahlausdruck mit Wert 2 ∈ IN boolean b = (x<7) || (++y!=0); Funktionen Bitoperatoren MSB einer short-Variablen Worin besteht der Unterschied ? Felder Zeichenausdruck mit Wert 50 ∈ IN syntaktisch falsch • Einerkomplement und Zweierkomplement m&3 k&0x8000 oder k&0100000 3L & 6L ’3’ & ’6’ 3.0 & 6.0 ˜n und ˜n+1 Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Schiebeoperatoren Anweisungen Felder Funktionen Σ Beispiele — Schiebeoperatoren Arithmetische versus logische Verschiebung Arithmetische Links- und Rechtsverschiebung Linker Operand x vom Ganzzahltyp Rechter Operand n vom Ganzzahltyp Das Resultat besitzt den Typ von x Typsicherheit am Beispiel einer byte-Variablen „Bitmuster“ der Länge ` „Schiebezähler“ ein „neues“ Bitmuster =β [x<<n] = (=β [x] · 2ν ) mod 2` =β [x>>n] = (=β [x] /2ν ) mod 2` Muster Zähler x 00001111 10001111 10001111 n 1 1 43 links arithmetisch logisch x<<n 00011110 00011110 01111000 x>>n 00000111 11000111 11110001 x>>>n 00000111 01000111 00010001 wegen x<<43 ≡ x<<3 Auswertung des Schiebezählers immer als Rest: Beispielausdrücke ν = =β [n] mod ` Links schieben Arithmet. rechts Logisch rechts << um ν Stellen links rechts mit Nullen füllen führende Bits verloren >> um ν Stellen rechts links mit VZ-Bit füllen hängende Bits verloren >>> um ν Stellen rechts links mit Nullen füllen hängende Bits verloren Bitmaske ξ`−1 . . . ξ2 ξ1 ξ0 mit Eins in Position n Zweierpotenz 2n EGST’s Lieblingsoperator 1 << n 1 << n m >>>= m Achtung! Es gilt einerseits =β [-1>>1] = −1, andererseits =β [-1/2] = 0. Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Wertverzweigung Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Beispiele — Wertverzweigung Syntax einer Wertverzweigung Dreistelliger Bedingungsoperator in Infixschreibweise: Wertverzweigungsausdrücke und ihre Resultate Betrag, AND/OR, Terminierung, Operatorvorrang B ? E1 : E2 Argument B ist ein boolescher Ausdruck. Argumente E1 , E2 sind Ausdrücke gleichen Typs ( =β [(x>=0 ? x : -x)] = |=β [x] | Ergebnistyp) =β [(a ? true : b)] = =β [a || b] Semantik einer Wertverzweigung =β [(false ? crashAdd(8,9) : 17)] = =β [17] = 17 ?: ist kein strikter Operator! =β [(true?17:4+3)] = =β [17] 6= =β [17+3] • Wert =β [B ? E1 : E2 ] = =β [(a ? b : false)] = =β [a && b] =β [E1 ] =β [E2 ] =β [B] = =β [true] =β [B] = =β [false] • Wirkung Genau einer der beiden Operanden E1 , E2 wird ausgewertet! Wirkung = ˆ Nebenwirkungen der Auswertungen von B und E1/2 Verwechslungsgefahr Kontrollverzweigungen in Java á la if (x>=0) y=x; else y=-x; Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Berechnung von Ausdrücken in Java 1. Klammerung respektieren 3*(17+4) ≡ 63 17-(-4) ≡ 21 17--4 ≡ ??? 2. Operatorvorrang Vorrang A. Aufbau eines Kantorovic-Baumes (E1 E2 ) ♦ E3 E1 (E2 ♦ E3 ) 3. Assoziationsrichtung (E1 ◦ E2 ) ◦ E3 E1 ◦ (E2 ◦ E3 ) Wirkungslose Klammerpaare können im Programmtext unterdrückt werden. Ausdrücke Typsicherheit Punkt- vor Strichrechnung: 3*17+4 ≡ 55 Vergleich bindet schwach: 20<=17+4 ≡ true meistens links-rechts: a+b+c ≡ (a+b)+c manchmale rechts-links: x=y=5 ≡ x=(y=5) Klammerersparnis Bezeichner 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Assoziation B. Traversierung in verträglicher Folge Anweisungen Felder Typsicherheit Anweisungen Felder Σ Funktionen Σ Bezeichner E++ E-A[E] E.N F(P) Postfix · Selektion · Applikation ++E --E +E -E ˜E !E unäre Präfixoperatoren new (T)E Erzeugung · Typanpassung * / % Punktrechnung + Strichrechnung << >> >>> Schiebeoperatoren <= >= < > Ordnungsrelationen == != Gleichheit · Ungleichheit & bitweises+logisches AND ˆ bitweises+logisches XOR | bitweises+logisches OR && bedingtes logisches AND || bedingtes logisches OR ?: Wertverzweigung = += -= *= /= %= >>= <<= >>>= &= ˆ= |= Zuweisung Ausdrücke Typsicherheit Anweisungen Felder Beispiele — Operatorenrang und -richtung Boolesche Operatoren Autoinkrement Ausdruck a&b == c&d bedeutet in Java a & (b==c) & d und in C++ (a&b) == (c&d). Sei β(x) = 17 und β(y) = 4. Lexikalische Ebene: Literale und Variablennamen Einfache Typen, Operatoren und Ausdrücke x+ ++y ≡ 17+5 x++ +y ≡ 17+4 Wertverzweigung x+++y ≡ 17+4 Der Ausdruck 17 + true?4:1 ist unsyntaktisch. x+ +y ≡ 21 Auch x +++y und x+++ y haben den Wert 21. Syntaktisch falsch: ++x++ ++(x++) (++x)++ x++y Funktionen Operatorpräzedenz und -assoziation (→,←) Klammern Auswertungsverfahren Ausdrücke Typsicherheit und Typkonversion Anweisungen, Blockstruktur und Kontrollfluß Referenzen und Felder Definition und Aufruf von Funktionen und Prozeduren Zusammenfassung Funktionen Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Typsicherheit Variablendeklaration Jeder Java-Ausdruck besitzt einen eindeutigen Datentyp Vereinbarung eines Bezeichners für wertveränderliche Datenobjekte Syntaktische Typermittlung Syntax Der Datentyp eines Ausdrucks ist zur Übersetzungszeit bekannt. Initialisierungsausdrücke vom deklarierten Typ • Variable und Konstanten sind deklariert double x; vardecl • Literale sind typspezifisch geformt 8.83f init • Operatoren besitzen eine Signatur 47*11, 47 >= 11 • Methoden (Funktionen) dto. Bemerkung Startwertausdruck mit deklarierten & definierten Variablen. ::= typ init [,init]∗ ; ::= name Verboten: float r, s=5*r; { = expr } Bemerkung Variablendeklarationen sind Anweisungen. Ausweitung des Zustandsraumes; kein Wert! a[5], stud.name • Wirkung Definition typ x = expr; Semantischer Feinschliff def β 0 = β[=β [expr]/x ] • Überladen von Operatoren und Methoden 47.0 * 11.0 • automatische Typkonversion 47.0d * 11.0f • willkürliche Typkonversion (short) 47.11 Ausdrücke Typsicherheit Anweisungen Felder Funktionen double x=17.0; ... ... ... ... ... ... x += 4.0; • Wirkung Deklaration typ x; def β 0 = β[⊥/x ] Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Konstantendeklaration Zuweisung Vereinbarung eines Bezeichners für wertfixierte Datenobjekte Die elementarste aller Anweisungen Syntax Initialisierungsausdrücke passen zum deklarierten Typ Beispiele Zuweisungsausdruck mit Semikolon: Deklariert sei: double x=12, y; final double PI=3.14, z=1/0F; ::= final vardecl vardecl ::= typ init [,init]∗ ; assign ::= lexpr = expr ; init ::= name { = expr } linker Operand: Linkswert & nicht konstant rechter Operand: alle Bezeichner deklariert & definiert Ausweitung des Zustandsraumes; kein Wert! • Wirkung Definition final typ x = expr; Bemerkung Konstantendeklarationen sind Anweisungen. def β 0 = β[=β [expr]/x ] • Wirkung Deklaration final typ x; (Konstantendeklarationen ohne Startwertausdruck gelten als „unschicklich“.) final int PI=3; ... ... ... ... ... ... m += PI/2; Funktionen Syntax constdecl Semantik Σ Semantik sqrt(5D), ggt(47,11) • Selektion ist typeindeutig Bezeichner Funktionen Semantik Verändert den Zustandsraum; kein Wert! • Wirkung der Zuweisung x = expr; def β 0 = β[=β [expr]/x ] Erlaubt x y y x = 17+4; = 17+4; = z - z; += 1; Verboten PI = 17+4; x = y/1000; x+2 = 17+4; y += 1; Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Typsicherheit Anweisungen Felder Typsystem Explizite Typkonversion Datentypen sind durch ihre Wertebereiche halbgeordnet Im Programmtext gefordert · aufwärts/abwärts Definition Problem Es seien σ1 und σ2 zwei Typen und σ1A bzw. σ2A ihre Trägermengen. Der Typ σ1 heißt Untertyp von σ2 falls gilt: In stark typisierten Sprachen sind inkorrekt: σ1A Es gibt drei mögliche Wertebereichskonfigurationen: long m = 8; float x = m; x = 17 + 4.0; • Typaufweitung („upcast“) Ausdruckwert kann verlustfrei übernommen werden σexpr ⊆ σtype • Typverengung („downcast“) Wertreduktion durch Ausmaskieren σexpr ⊇ σtype byte ⊆ short ⊆ int ⊆ long ⊆? float ⊆ double Wo bleiben Wahrheitswerte und Zeichen? 1. Vorzeichenverlust (Betragsbildung) 2. Präzisionsverlust (Nachkommastellenschwund) 3. Dynamikverlust (Überlauf/Unterlauf) Die Halbordnung elementarer Typen in Java Ausdrücke int Typsicherheit long float Anweisungen Felder • Unvergleichbarkeit Syntaxfehler double Funktionen Σ Bezeichner Ausdrücke σexpr * σtype σexpr + σtype Typsicherheit Anweisungen Felder Typverengung Typaufweitung Abwärtsanpassung — ausschließlich durch explizites Erzwingen Aufwärtsanpassung — explizit oder implizit Typverengung auf 8-Bit-Ganzzahlwerte (byte) Automatische Typanpassung Ausmaskieren und vorher erforderlichenfalls Abrunden Quelltyp =β [x] =β [x]16 =β [(byte) x] Vom Compiler ungefragt initiiert short-Variable (16-Bit) 128 0080 -128 129 0081 -127 127 007F 127 -128 FF80 -128 Σ castex ::= ( type ) expr Es gelten folgende Relationen: char byte boolean < short Funktionen Syntax und Semantik des „cast“-Operators σ2A ⊆ Typ σ2 heißt dann Obertyp von σ1 . Bezeichner Ausdrücke 256 0100 0 float 257 0101 1 255 00FF -1 -13.5 F..F4 -13 • ausschließlich in Aufwärtsrichtung • Ausdrücke, Zuweisungen, Parameterübergaben Funktionen Vollautomatisch 1 + 1.0f ∈ Tfloat 1 + 1.0 ∈ Tdouble 1L + 1.0f ∈ Tfloat 1 + 1L ∈ Tlong Schachtelung Typerzwingung abwärts/aufwärts zur Variablendefinition Zweistellige arithmetische Operatoren Aufweitung immer von innen nach außen int x = (int) 1L; char z = (char) 127; byte c = (byte) (a+b); // long -» int // int -» char (DEL-Zeichen) // ??? -» byte, Reduktion mod 256 Gips nur für typgleiche Operandenpaare: int, long, float, double Überraschung! int m = (int) true; double r = (double) 17; // SYNTAXFEHLER !!! • Aufweitung zum größeren der beiden Operandentypen Vgl. Deklarationen double d = 1/2; und double d = 1.0/2; // okay, aber obsolet • „Rechnen“ mindestens in int !! =β [0.8 + 1/2] = 0.8 =β [0.8 + 1/2f] = 1.3 Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Datentypen short und byte Typsicherheit Anweisungen Felder Funktionen Σ Komplexer Datentyp String Elementare ALDI-Ganzzahltypen zur Speicherplatzersparnis Ausdrücke vom Spartyp sind extrem selten, denn: ⊕ Sparvariable Diplomatisches Java! Krone der Schöpfung Verkettungsoperator Der Zeichenkettentyp ist Obertyp aller elementaren Datentypen Der eingebaute Operator Compiler ist freundlich, aber leider unberechenbar: byte b, b1=5, b2=10; Sparliterale Sparoperatoren Überraschende Syntaxfehler Nach der Deklaration byte a=1, b=2, c=3; sind syntaktisch inkorrekt: a = -b; c = a+b; Aufweitung Zahlwerte in Dezimaldarstellung Korrekte & inkorrekte Folgezuweisungen b b b b b = = = = = 0; 50; 500; 5 * 10; b1 * b2; // // // // // Ausdrücke Typsicherheit Anweisungen Felder Automatische Typanhebung für alle elementaren Typen Es seien Konstanten via final float pz = 1/0F, mz = -1/0F; definiert. ok ok Syntaxfehler ok Syntaxfehler Funktionen verkettet zwei Zeichenreihen. Denksportaufgabe =β ["Wert =β ["Wert =β ["Wert =β ["Wert =β ["Wert Warum eigentlich? Bezeichner + : String × String → String Σ Bezeichner Ausdrücke = = = = = " " " " " + + + + + = = = = = pz] mz] (pz+pz)] (pz+mz)] pz+mz] Typsicherheit „Wert „Wert „Wert „Wert „Wert Anweisungen = = = = = Infinity“ -Infinity“ Infinity“ NaN“ Infinity-Infinity“ Felder Funktionen Anweisungen Die zentralen imperativen Konstrukte einer Programmiersprache Lexikalische Ebene: Literale und Variablennamen Einfache Typen, Operatoren und Ausdrücke Syntax und Semantik von Anweisungen Wirkung = ˆ Zustandsänderung • in Java oft durch „;“ abgeschlossen Typsicherheit und Typkonversion • besitzen grundsätzlich keinen Wert S β =⇒ β 0 • durch ihre Wirkung charakterisiert Interpretation ist Abbildung Anweisungen, Blockstruktur und Kontrollfluß Referenzen und Felder = [S] : Z → Z ⊥ 1 Zustandssemantik C "nachher" Definition und Aufruf von Funktionen und Prozeduren "vorher" 2 3 4 def 6 β 0 = = [S] (β) ∈ Z 5 ∋ β Z β’ ∋ Zusammenfassung von Vorzustand β ∈ Z auf Z Zustandsübergangsfunktion = [S] (resultierender Nachzustand nach Ausführung von S) Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Übersicht — Anweisungsarten ::= decstm | exstm | cfstm | ; ::= assex ::= lexpr [ =|+=|-=|*=|/=|%=|&=||=|ˆ=| . . . ] expr autex ::= cfstm ::= block | ifstm | switchstm | whilestm | dostm | forstm | m+=4; c++; int m=17; { x = 4; y = 7; } oder { n = 4; n = 7; } oder { n = 7; n = 4; } entspricht der Hintereinanderschaltung der Einzelwirkungen ( β n=0 = [S1 . . . Sn ] (β) = = [S2 . . . Sn ] (= [S1 ] (β)) n>0 Ausdrücke move(x,y); 17+4; Wirkungsweise einer Anweisungssequenz final float PI=314e-2f; if (a>0) x=a; 5. Anweisungsblock Bezeichner (Klammern objektsprachlich) Semantik einer Anweisungssequenz ; 4. Kontrollfluß = [x=4; y=7;] (β) = = [y=7;] (β[4/x]) = β[4/x, 7/y] while(n-->0) x+=n; Keine Kommutativität: = [n=4; n=7;] (β) = β[7/n] { int x,y; x = 17; y = x+4; } Typsicherheit Σ [ lexpr [++|--] ] 1. leere Anweisung 3. Deklaration Funktionen Beispiel block ::= { statement ∗ } Beispiele 2. Ausdrucksanweisung Felder Syntax eines Anweisungsblocks [ assex | autex | callex ] ; exstm [ [++|--] lexpr ] Anweisungen Anweisungsfolgen Syntax einer Java-Anweisung statement Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Geschachtelte Blockstruktur Typsicherheit 6= β[4/n] = = [n=7; n=4;] (β) Anweisungen Wo und wie lange „gelten“ deklarierte Variable ? Blocktiefe Jeder Block ist wiederum eine Anweisung. Blöcke lassen sich verschachteln. Auch {} ist eine Anweisung. float f,g,h; // Tiefe 0 f = 17; f += g = h = f; Bereich { int x = 1; int y; // Tiefe 1 Definition // Tiefe 2 Ein Bezeichner heißt lokal für den Block seiner Deklaration — andernfalls heißt er global (oder undefiniert). // Tiefe 1 Gültigkeitsbereich („scope“) // Tiefe 0 Lebensdauer des Bezeichners abzüglich überdeklarierter Bereiche Induktive Definition der Blocktiefe einer Anweisung: • Tiefe 0 vor erster und hinter letzter Blockklammer eines Programmtextes • Erhöhung um 1 nach Betreten eines neuen Blocks • Verminderung um 1 nach Verlassen des aktuellen Blocks Leben und Geltung Lebensdauer („lifetime“) { int z = 2; y = z; } y = x; } double a=5F; short people; Funktionen Lokale und globale Variable Blockschachtelung Schachtelungstiefe Felder Deklaration des Bezeichners abschließende Blockklammer { int x = 7; int y; { int x = 8; y = x; } y -= x; } x /= y; int x = 9; y *= x; // x #1 // x #2 // x #2 // x #1 // ?!? // x #3 // ?!? Namensinstanzen Kein Block: Überdecken von Variablennamen int m; m = 17+4; (und auch keine Anweisung) in untergeordneten Blöcken ist in Java verboten & in C++ erlaubt! Die (2)Deklaration von x über steht neben x(3) der Deklaration von x(1) Σ Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Pulsierender Stapelspeicher // Block 1 { int y=1; x = y; } // Block 1.1 Dynamische Variable erhalten sie zur Laufzeit. { int y=2; x = y; } // Block 1.2 dynamisch { int x; Statische Variable erhalten Adresse bei Übersetzung. Halde frei Abhängig vom Wert eines booleschen Ausdrucks übernimmt ein Anweisungszweig (oder ein anderer) die Kontrolle: B1 B1.1 Bezeichner x x B1 B1.2 B1 Ausdrücke Typsicherheit Stapel lokale V. statisch globale V. Felder (else) B S2 { else statement } Semantik der ein- und zweiseitigen Verzweigung Funktionen = [S1 ] (β) β =β [B] = L =β [B] = O = [S1 ] (β) = [S2 ] (β) =β [B] = L =β [B] = O = [if(B) S1 ] (β) = = [if(B) S1 else S2 ] (β) = Σ Bezeichner Einseitige und zweiseitige Verzweigung Ausdrücke Typsicherheit Anweisungen Felder Funktionen Geschachtelte Verzweigungen if-Anweisung mit/ohne else-Zweig Einseitige Verzweigungen Spezialfall trivialer S2 -Zweig: Achtung! Nebenwirkungen Verzweigung & Wertverzweigung Die vereinfachte Semantikdefinition gilt nur für nebenwirkungsfreie Bedingungsausdrücke. Die zweiseitige Verzweigung („Betragberechnung“) Gegenbeispiel if (B) S1 ≡ if (B) S1 else ; Verzweigungen sind Anweisungen Dangling else und lassen sich folglich schachteln: Besser Klammern verwenden, denn if (a <= 0) res = a; else if (a+b < 0) res = a+b; else res = b; if (B1 ) if (B2 ) S1 else S2 sieht syntaktisch mehrdeutig aus. (eindeutig trotz fehlender {, }) if (a >= 0) res = a; else res = -a; besitzt dieselbe Wirkung wie die Wertverzweigung res = (a >= 0) ? a : -a; Σ ifstm ::= if (bexpr ) statement anonyme V. „Garbage collection“ löscht anonyme Variable, die ihre letzte Referenz verloren haben. Anweisungen if S1 Speicherbereinigung x Funktionen false Speicherorganisation y x Felder Syntax für Verzweigungen Leben und Sterben in Java y x Anweisungen Bedingte Anweisungen für lokale Programmvariable } Typsicherheit true Bezeichner if (++i < 17) x += i; else x -= i; Die Lesarten des „dangling else“ sind auch semantisch ambig: B1 B2 L L if (B1 ) { if (B2 ) S1 else S2 } S1 if (B1 ) { if (B2 ) S1 } else S2 S1 L O O L S2 {} {} S2 O O {} S2 in Java Σ Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Fallunterscheidung Testausdruck Ganzahltyp ∗ switchstm ::= switch (gexpr ) { case default } case ::= [case gconst:]+ statement break; default ::= {default: statement} Beispiel „Kalendermonate“ switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break; case 4: case 6: case 9: case 11: days = 30; break; case 2: days = 28; break; default: Out.println ("error"); } Abfangklauseln Fallunterscheidung Objektcode benutzt eine Sprungtabelle if (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12) days = 31; Schlüsselwort case ≥ 1 Klausel (Werte 6=) statisch und ganzzahlig else if (month== 4 || month==6 || month==9 || month==11) days = 30; Sammelklausel else if (month==2) days = 28; default (Fehlanzeige) else Klauseltests Out.println ("error"); Abarbeitung in der Reihenfolge ihrer Aufschreibung Anweisungen Felder Funktionen Unter Umständen zwölf Vergleichsoperationen! Σ Bezeichner Ausdrücke Wiederholungsanweisungen do while false B S true B for false S Typsicherheit Anweisungen Felder Funktionen Semantik S beg S Σ ... ... ... ... 01 02 03 04 05 06 07 08 09 10 11 12 default days=31 days=30 days=28 "error" ... ... ... ... Abweisende Wiederholungsschleife „Iteration“ — abweisend · nicht abweisend · gezählt while Funktionen Realisierung ohne Fallunterscheidung break verläßt Fallunt. Sollte nicht fehlen! Typsicherheit Felder Kaskadierte Verzweigung Absprung int days, month = In.getInt(); Ausdrücke Anweisungen Fallunterscheidungen sind effizient Syntax für die Fallunterscheidung Bezeichner Typsicherheit months Bezeichner Sincr B true false true Booleschen Ausdruck auswerten und ggf. den Schleifenrumpf ausführen β =β [B] = O = [while(B) S] (β) = = [while(B) S] (β 0 ) =β [B] = L def mit dem S-Folgezustand β 0 = = [S] (β) Syntax für die drei Iterationskonstrukte Beispiel Summation Terminierung Wiederholt Anweisung solange boolescher Ausdruck wahr ist Berechne 1 + 2 + . . . + 9 = 45 Anzahl S-Ausführungen ∈ IN0 ∪{∞} S ändert (i.a.) Zustand und =β [B] whilestm ::= while (bexpr ) statement dostm ::= do statement while (bexpr ) ; forstm asslist ::= ::= for (forinit; bexpr ; asslist) statement assex [ , assex ]∗ forinit ::= declaration | asslist { int i = 1, res = 0; while (i < 10) { res = res + i; i++; } } Invariante Ausgangssituation nach einmaliger Rumpfausführung — abgesehen von β 0 6= β Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Nicht abweisende Wiederholungsschleife for (S0 ; B; SI ) S def Wieder ist β 0 = = [S] (β). Mindestens eine S-Ausführung Mindestens ein B-Test { Startdeklaration Berechne 1 + 2 + . . . + 9 = 45 für die Laufvariable { { Ausdrücke Semantische Äquivalenz Anweisungen Felder Funktionen int res = 0; for (int i = 1; i < 10; i++) res = res + i; } } do S while (B); ≡ { S; while (B) S } Typsicherheit int i = 1, res = 0; for (i = 1; i < 10; i++) { res = res + i; } } Bezeichner Σ Barbarischer Programmierstil: Warum geht das so nicht? for (int i=1; i<10; res += i++) ; for (int i=1, res=0; i<10; i++) res+=i; Bezeichner Ausdrücke Beispiel — Primzahltest und Endlosschleife Typsicherheit Anweisungen Felder Funktionen Markierung, Ausbruch und Fortsetzung Edsger, der Rotterdamer, hätte das nicht gewollt! Primzahltest durch Probedivision final int boolean int N = In.readInt(); prim = true; teiler = 2; Endlosschleife Wiederhole den Rumpf „bis daß der Tod uns scheide“. while (true) S Syntax labstm ::= name : statement breakstm ::= break {name}; continstm ::= continue {name}; oder while (teiler < N && prim) if (N % teiler == 0) prim = false; else teiler++; Out.println ( N + " ist prim: " + prim ); Rechtzeitiges Verlassen der Schleife mittels boolescher Signalvariable prim. do S while (true); oder for (;;) S wegen der semantischen Äquivalenz while (B) S ≡ for (;B;) S Σ ≡ { S0 ; while (B) {S; SI ;}} Beispiel Summation int i = 1, res = 0; do { res = res + i; i++; } while (i < 10); Funktionen Startanweisung, dann Wiederholung von Rumpf und Fortschaltung Schleifenrumpf unbedingt ausführen, danach erster Wahrheitstest 0 β =β 0 [B] = O = [do S while(B);] (β) = 0 = [while(B) S] (β ) =β 0 [B] = L Berechne 1 + 2 + . . . + 9 = 45 Felder Semantische Äquivalenz Semantik Terminierung Anweisungen Gezählte Wiederholungsschleife Charles-Bronson-Iteration: „Erst schießen — dann fragen“ Beispiel Summation Typsicherheit Single entry single exit ? Gilt in Java mit zwei Ausnahmen: break · vorzeitiges Verlassen eines Blocks continue · vorzeitiges Wiederholen eines Rumpfes Marken und Sprünge Jede Java-Anweisung kann markiert werden. Starke Einschränkung für mögliche Sprungziele: • Startanweisung umschließender Verzweigungsoder Wiederholungsblöcke E.W. Dijkstra 1930–2002 Wege im Graphen Semaphoren (Synchr.) goto nein danke! Strukt. Programm. Turing Award 1972 Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Ausdrücke Typsicherheit Anweisungen Felder Unmarkierter Ausbruch Markierter Ausbruch Beendet die umgebende Schleife oder Fallunterscheidung Beendet angesteuerte Schleife oder Fallunterscheidung Beispiel — Berechnung des Zeichencodes Resultat final char CH = ’Ä’; Das Programmfragment liefert die Ausgabe char(196) = Ä for (int i = 0; i < 256; i++) if (i == CH) { Out.println ("char(" + i + ") = " + CH); break; } Beispiel — Faktorenzerlegungstest while, for Sie beendet den innersten umgebenden Block vom Typ do, switch Anweisungen Resultat Die Wirkung der break label-Anweisung Beendet den mit label markierten Umgebungsblock • Anwendungszweck: Verlassen einer scheinbaren Endlosschleife Abbruch einer Fallunterscheidung nach der Abfangklausel Typsicherheit Felder • Syntaxfehler falls kein solches Ziel existiert! (keine beliebige Einsprungposition wie goto) Funktionen Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Unmarkierte Fortsetzung Setzt die umgebende Schleife mit nächster Rumpfausführung fort Beispiel — Zählen dualer Einsbits Resultat final int MASKE = 0x1111000F; int einsen = 0; Das Programmfragment liefert die Ausgabe 286326799 hat 8 Einsen for (int i = 0; i < 32; i++) { int msr = MASKE >>> i; if (msr%2 == 0) continue; einsen++; } Out.println (MASKE + " hat " + einsen + " Einsen"); Die Wirkung der continue-Anweisung Transferiert den Kontrollfluß der umgebenden Wiederholungsanweisung zum nachfolgenden Schleifendurchlauf Σ • Syntaxfehler falls ein solcher nicht existiert! Ausdrücke Funktionen Das Programmfragment final int N = 4711; liefert die Ausgabe boolean zbar = false; 4711 ist zerlegbar home: for (int i = 2; i < N; i++) for (int j = 2; j < N; j++) Zweck if (i * j == N) { gleichzeitiges Verlassen zbar = true; geschachtelter Schleifen break home; } Out.println (N + " ist" + (zbar?"":" nicht") + " zerlegbar"); Die Wirkung der break-Anweisung Bezeichner Bezeichner while (B) S Abweisungstest B do S while (B); fährt fort mit Abbruchtest B for (S0 ;B;SI ) S Fortschaltung SI und Fortsetzungstest B Lexikalische Ebene: Literale und Variablennamen Einfache Typen, Operatoren und Ausdrücke Typsicherheit und Typkonversion Anweisungen, Blockstruktur und Kontrollfluß Referenzen und Felder Definition und Aufruf von Funktionen und Prozeduren Zusammenfassung Funktionen Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Wertvariable und Referenzvariable Typsicherheit Anweisungen Felder Funktionen Σ Reihungen in Java in der Sprache Java und anderswo ... Identifikatoren für Datenobjekte Stufe Stufe Stufe Stufe Stufe Stufe a ∈ Mσ Datenobjekt Variable Referenz ... ... 0 1 2 3 4 5 Reihungen sind zusammengesetzte Datentypen Literal (Wertname) klassische Variable/Konstante Referenz (auf) Variable doppelte Indirektion dreifache Indirektion ... ... ... Java-Typen: elementar komplex ·/· ·/· ·/· • Basistyp = ˆ beliebiger elementarer oder komplexer Typ • mehrdimensionale Reihungen durch Schachtelung • es gibt Literale für (mehrdimensionale!) Reihungen • Reihungsvariable sind Referenztypen • Reihungselemente konsekutiv auf der Halde abgelegt Variablen beliebiger Ordnung in C++ double **z Bezeichner Ausdrücke double *y double x Typsicherheit Beispiel int n = 2; int &r = n; int five = n+r+1; r += 7; int m = 12; r = m; 15.0e+8 Anweisungen Felder Funktionen Eindimensionale Reihungen Deklaration einer Reihungsvariablen Typname T , neuer Bezeichner x T [] x; Stapel x (Nichtnegativer) Ganzzahlausdruck n Halde x[0] x[1] x[2] x[3] x[4] `(x) = 5 Wirkung Initialisierung eines Reihungsobjekts Ausdrücke E1 , . . . , En vom Typ T T [] x = new T [] {E1 , . . . , En } ; ArrayIndexOutOfBoundsException • Initialisierung wie bei Objektkomponenten (Variante der Null) Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Syntax für Komponentenzugriff und Feldlänge arrayname [ intexpr ] bzw. arrayname . length Deklaration char [] seq; char [] seq0 = null; seq seq0 1. Referenzvariable 2. Haldenobjekte erzeugt (und vermerkt). seq0.length ≡⊥ (Syntaxfehler!) ≡ null ≡⊥ Deklaration & Erzeugung double [] zero = new double[8]; zero Es werden je nachdem 3. Feldeinträge Der Ausdruck {E1 , . . . , En } heißt „Feldliteral“ Σ • Feldgrenzenüberschreitung wird als Laufzeitfehler geahndet Deklaration und Selektion für eindimensionale Felder Speicherstruktur Erzeugung eines Reihungsobjekts T [] x = new T [n] ; (anonyme Variable) zero[5] zero.length zero[8] Deklaration & Erzeugung & Vorbesetzung int [] vec = new int[] {1,2,3,4,5}; vec vec[3] vec[0] vec[5] ≡ ≡ ≡ ≡ Adresse 0.0d 8 ⊥ ≡ ≡ ≡ ≡ Adresse 4 1 ⊥ Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Beispiel — Primzahltest mit Siebverfahren AD Eratosthenes von Kyrene (etwa 276 AD Kyrene – 194 Typsicherheit Anweisungen Felder Funktionen Σ Mehrdimensionale Felder Alexandria) Matrix = ˆ Reihung einer Reihung Mehrdimensionale Felder werden durch Schachtelung realisiert final int N = In.readInt(); boolean[] tilt = new boolean[1+N]; for (int i=0; i<=N; i++) tilt[i] = i < 2; a21 a22 a23 // nötig? a31 a32 a33 a41 a42 a43 [email protected] int k = 2; ⇔ Primzahlsiebalgorithmus while (k*k <= N) { if (!tilt[k]) for (int j=k; j<=N; j+=k) tilt[j] = true; k += 1; } `=4 Ausdrücke Typsicherheit " Anweisungen Felder Funktionen mat mat.length mat[8].length mat[88][8] Deklaration & Erzeugung & Vorbesetzung rag rag.length rag[0].length String String[] String[][] String[][][] word line page book = = = = a[1] a[1][0] a[1][1] a[1][2] a[2] a[2][0] a[2][1] a[2][2] a[3] a[3][0] a[3][1] a[3][2] `=3 ⇔ rag[1].length rag[0][0] rag[1][1] rag[2][2] rag[0] ”Akrützel”; {word,word,word,word,word,word}; {line,line,line,line,line}; {page,page,page}; Σ Bezeichner Ausdrücke Halde b[0] Halde b[0][0] b[0][1] b[1] b[1][0] b[1][1] b[1][2] b[2] b[2][1] ` =? Typsicherheit Anweisungen Felder Funktionen Zuweisen und Kopieren mit Reihungen Wertvariable und Referenzvariable Deklaration & Erzeugung Dreidimensionale Reihungen b11 b12 b21 b22 b23 b31 Stapel b # `=3 Wegen Schachtelung keine spezielle Syntax notwendig int[][] rag = {{11,12},{21,22,23},{31}}; Halde a[0][0] a[0][1] a[0][2] Flatterrandtabellen mit Zeilen ungleicher Länge Deklaration und Selektion für mehrdimensionale Felder float[][] mat = new float[365][24]; Halde a[0] http://de.wikipedia.org/wiki/Sieb_des_Eratosthenes for (int i=2; i<=N; i++) if (!tilt[i]) Out.print (i + ", "); Bezeichner a11 a12 a13 Stapel a ≡ ≡ ≡ ≡ ≡ ≡ ≡ ≡ ≡ ≡ ≡ ≡ Adresse 365 24 0.0f Adresse 3 2 3 11 22 ⊥ {11,12} int[] g; { int[] a,b; a = new int[5]; g = new int[] {2,3,5,7}; b = {2,3,5,7}; a[3] = 17; b = a; a = b = new int[7]; a[2] = b[2]; } final int FÜNF = g[2]; globale Referenzvariable undefinierte Referenzvariablen Verweis auf neues Objekt zuweisen Zuweisung an globale Variable; ok Syntaxfehler ← {...} ist kein Literal Feldkomponente verändern nur der Verweis wird kopiert! erstes Feld „vogelfrei“ ändert nix; schadet nix (=β [b[2]] = 0) a,b weg; drittes Feld „vogelfrei“ zweites Feld lebt noch Tiefes Kopieren von Objekten int[] b = {47,11}; int[] c = new int[b.length]; for (int i=0; i<b.length; i++) c[i] = b[i]; int[] b = {47,11}; int[] c = (int[]) b.clone(); Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Funktionen Σ Zählschleife in Iteratorform (ab Java Version 5) Lexikalische Ebene: Literale und Variablennamen Syntax der Schleife über Reihungselemente Einfache Typen, Operatoren und Ausdrücke Gebundene Variable = ˆ Reihungselementetyp Typsicherheit und Typkonversion foreach ::= for ( typeid compid : array ) statement Kommandozeilenargumente Tabelleninhalte ausgeben class Papagei{ public static void main (String[] arx){ for (String arg:arx) Out.print(arg+” ”); } } float[][] tab = {{11,12},{21,22,23},{31}} ; for (float[] row:tab){ for (float item:row) Out.print (item+” ”); Out.println (””); } Argumente ausdrucken: java Papagei Ich habe fertig Bezeichner Ausdrücke Typsicherheit Felder Funktionen Funktionen in der Mathematik oder Definition und Aufruf von Funktionen und Prozeduren Zusammenfassung Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Syntax einer Funktionsdeklaration in Java v u n X def u dist(x, y ) = t (xi − yi )2 public static T f (T1 x1 , . . . , Tn xn ) |{ | {z } | {z } Zusätze Kopf („Signatur“) S {z Rumpf }} i=1 k=0 Das Konzept mathematischer Funktionen Kompakte linke Seite = ˆ Abkürzung für die umfangreiche rechte Seite Zusatz = ˆ Qualifikatoren Deklaration public: außerhalb der Klasse sichtbar static: Klassenmethode ohne Objektbezug nur Signatur abstrakte Methode • die Funktion besitzt einen Namen Kopf = ˆ Signatur • die Funktion besitzt eine Berechnungsvorschrift f Methodenbezeichner · T sein Ergebnistyp T1 , . . . , Tn Typen formaler Parameter x1 , . . . , xn Namen formaler Parameter • die Funktion besitzt einen Ergebniswert • die Funktion besitzt Argumente Die Argumentnamen sind beliebig Felder Funktionen in der Programmierung Funktionen mit einem/zwei Argument(en) ∞ X x 2k+1 def sin(x) = (−1)k (2k + 1)! Referenzen und Felder 11 12 21 22 23 31 Ausgabe: Anweisungen Anweisungen, Blockstruktur und Kontrollfluß Wertebereich Anzahl, Namen, Wertebereiche „gebundene Variable“ Rumpf = ˆ Implementierung x1 , . . . , xn lokale Variablen des Blocks Definition Kopf & Rumpf konkrete Methode Aufruf aktuelle Parameter für formale Parameter Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Ausdrücke Typsicherheit Anweisungen Felder Funktionen Beispiele — Ergebnisrückgabe in Funktionen Funktionsaufruf Die Ausbruchanweisung return expr ; Funktionsapplikationen sind Ausdrücke des Rückgabetypes Syntax einer Funktionsapplikation Quadrieren einer Zahl Quadrieren mit Rekursion Rumpf als return-Anweisung Rumpf ruft sich selbst auf int quad (int n){ return n*n; } int quad(int n){ return (n==0) ? 0 : quad(n-1) + 2*n - 1; } Harmonische Reihenglieder Primzahltest Rumpf endet mit return Rumpf wird vorzeitig verlassen double harm (int k){ double res = 0.0; for (int i=1; i<=k; i++) res += 1.0/i; return res; } boolean isprime (int n){ for (int k=2; k<=n/2; k++) if (n%k == 0) return false; return true; } Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Semantische Äquivalenz Komplikationen Der Funktionsaufruf Potentielle Einflußgrößen auf den Rückgabezustand β 0 : T y = f (E1 , . . . , En ) nach einer rekursionsfreien Deklaration Rumpfwirkungen in den S1 . . . Sk f (T1 x1 , . . . , Tn xn ) { S1 . . . Sk return E ; } ist semantisch äquivalent zum Fragment { T1 x1 = E1 ; ··· ··· ··· Tn xn = En ; S1 . . . Sk T y = E; } callex ::= funcid ( {expr [,expr ]∗ } ) Parameter sind Ausdrücke passenden Typs Nebenwirkungsfreie Semantik =β [f (E1 , . . . , En )] Auswertung von Funktionsaufrufen T Bezeichner Wertausbruch weitere (bedingte) return-Anweisungen Nebenwirkungen Auswertung aktueller Parameter E1 , . . . , En Selbstaufrufe rekursive f -Deklaration = =β 0 [E ] mit Σ β 0 = β[=β [E1/] x1 , . . . , =β [En/] xn ] für NW-freien Aufruf und rekursionsfreie (f 6∈ E ) Ausdrucksdeklaration: T f (T1 x1 , . . . , Tn xn ) { return E ; } Bezeichner Ausdrücke Typsicherheit Anweisungen Parameterübergabe Die aktuellen Parameter Ei werden ausgewertet und den formalen Parametern xi als Anfangswert übermittelt. Beispielaufrufe final int n=3; boolean[] alltrue = { isprime (17), !isprime (5*7), quad (2*n) == 36, quad(quad(n)) == 81, isprime (quad(n)/n) }; Felder Funktionen Wertparameter und Referenzparameter Hypothet. Programmfragment static double glov = 47.11; ··· ··· ··· boolean fun (int x1, char[] x2) { x1++; x2[0] = ’ö’; glov += 883; return true; } ··· ··· ··· int n = 5; char[] a = new char [2]; ··· ··· ··· boolean res = fun (n, a); Funktionsaufruf ändert a[0] und glov, aber nicht n. Σ Wertparameter Wert von x1 ist nach Blockende verloren Wert von n bleibt unverändert Referenzparameter Linkswert von x2 geht verloren. Linkswert von a geht verloren. Veränderung des Feldes (Halde) bleibt bestehen Implizite Parameter Weitere Nebenwirkungen von fun durch Zuweisung an globale Variable glov Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Eingabeparameter und Ausgabeparameter Eingabeparameter Eingabeparameter Ausgabeparameter Transiente Parameter ◦ • • Rückgabe mehrerer Resultate Ausdrücke Typsicherheit void f ( T1 x1 , . . . , Tn xn ) { S } Verlassen des Rumpfes mit Rückkehrklausel return; (ohne Ergebnisausdruck) Felder Beispiel — Funktion und Prozedur Funktionen Warteschleife Semantik einer Prozedurdeklaration int[] divide (int p, int q) { return new int[] { p/q, p%q }; } ··· ··· ··· final int vier = divide(14,3)[0]; final int zwei = divide(14,3)[1]; Anweisungen Σ Pseudoergebnistyp void • ◦ • Referenzparameter (rhs) globale Variable Wertparameter Bezeichner Funktionen Syntax einer Prozedurdeklaration Zuweisungsposition linke Seite rechte Seite Beispiel Referenzparameter (lhs) globale Variable Rückgabewert Felder Methoden ohne Rückgabewert Eingabe Ausgabe Anweisungen Prozedurdeklaration Zweckbestimmung von Funktionsparametern Parametertyp Wert- Referenz• • • • Typsicherheit • Aufrufwert kein Rückgabewert void sleep (int n){ while (n– > 0) ; } • Aufrufwirkung ← Zweck Wirkung der Rumpfanweisungen Nebenwirkung der Parameterauswertung Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Überladen von Funktionsnamen Beispiel — das Maximum zweier Zahlen Bitmuster erzeugen & drucken int composeBitPattern (int[] position){ int res = 0; for (int i=0; i<position.length; i++) res |= (01 << position[i]); return res; } void printBitPattern (int z){ for (int mask=01<<31; mask!=0; mask>>>=1) Out.print (((z&mask) != 0) ? ’1’:’0’); Out.println (); } Der Aufruf printBitPattern (composeBitPattern (new int[] {0, 23, 31})); erzeugt die Bildschirmausgabe 10000000100000000000000000000001 Argumente gleichen Typs Abweichende Typen Für Aufruf max(2.4,3.6) deklariere double max (double x, double y){ return (x>y) ? x : y; } Nach automatischem Aufweiten lassen sich auch max(2.4,5f) oder max(3,2e1) auswerten. Argumente niederen Typs Kreidezeittechnik Aufruf max(2,3) ergibt nach Aufweitung ein Resultat vom Typ double! Variantenzoo deklarieren Automatische Typaufweitung Überladen zu einem Standardangebot von Methoden eines einzigen Methodennamens mit mehreren Signaturen double dmax (double x, double y) float fmax (float x, float y) long lmax (long x, long y) int imax (int x, int y) Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Aufweitung von Signaturen Definition Die Signatur f (T1 , . . . , Tn ) heißt spezieller als f (T 0 1 , . . . , T 0 n ) wenn für alle i = 1, . . . , n gilt: Ti ⊆ Ti0 Typsicherheit Anweisungen Felder Funktionen Σ Beispiel eines Überladungskonflikts Bemerkung Signatur = ˆ Anzahl/Typen (ohne Rückgabetyp!) Angebotsmethoden für Maximumbildung long max (long n, long m) long max (int n, long m) long max (long n, int m) Relation „spezieller als“ ist eine Halbordnung, keine totale Ordnung. { return (n>m) ? n : m; } { return (n>m) ? n : m; } { return (n>m) ? n : m; } Typaufweitung 1 Aufrufe und ihre Desambiguierung Verwendung einer allgemeineren Funktion, wenn keine Funktionsdefinition mit exakt passender Signatur verfügbar ist. max (long,long) Desambiguierung 2 max (long,int) Übersetzer wählt die speziellste aller aufgeweiteten Signaturen aus, für die eine Deklaration vorliegt. f(1L,2L) f(1L,2) f(1,2L) f(1,2) Konfliktsituation 3 Gibt es mehr als ein minimales Element, so wird vom Übersetzer ein Syntaxfehler diagnostiziert! Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner max (int,long) • ◦ ◦ ◦ • • Ausdrücke Typsicherheit • • Anweisungen Felder Mechanismen der Parameterübergabe Beispiele in Java und anderswo für Übergabemechnismen und ihre Wirkungen √ √ √ ?! Funktionen Aufrufmechanismus Java Aufrufszenarium Effizienzfrage Formale Parameter xi Aktuelle Parameter Ei Wertaufruf mit Verweisen für Feldund Klassenobjekte int i = 0; int[] a = new int[] {0, 8, 15}; ··· ··· ··· void proc (int x) { i = i+1; x = x+2; } ··· ··· ··· proc (a[i]); double poly (double x){ return 5 + 4*x + 3*x*x + 2*x*x*x; } 1. Wertaufruf „call-by-value“ C++ Wert(Ei ) 2. Referenzaufruf xi „call-by-reference“ Explizite Auswahl zwischen Wert- und Referenzaufruf Matrix u vs. Matrix& u Linkswert(Ei ) 3. Namensaufruf xi „call-by-name“ S[E1/x1 , E2/x2 , . . . , En/xn , ] LATEX Makrodefinitionen mit Namensaufruf \newcommand Reihungsobjekt — hinterher WA (keine Auswirkung) a ≡ {0, 8, 15} RA (wegen x ≡ a[0]) a ≡ {2, 8, 15} NA (Manipuliert a[i]) a ≡ {0, 10, 15} nebst poly (sin(3)/exp(7)); Terminierungsfrage double ifelse (boolean b, int i, int j){ return b ? i : j; } nebst ifelse (true, 5, trick(17)); Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Σ Bezeichner Ausdrücke Typsicherheit Anweisungen Felder Funktionen Zusammenfassung Lexikalische Ebene: Literale und Variablennamen 1. Ein Java-Programm ist eine Menge von Klassendeklarationen. Einfache Typen, Operatoren und Ausdrücke 2. Für die 8 Basistypen sind Literale definiert sowie arithmetische und logische Operationen. Typsicherheit und Typkonversion 3. Die Auswertungsreihenfolge für Ausdrücke richtet sich nach Klammerung, Operatorvorrang und Assoziationsrichtung. 4. Java ist typsicher, besorgt aber automatische Typaufweitung. Anweisungen, Blockstruktur und Kontrollfluß Referenzen und Felder Definition und Aufruf von Funktionen und Prozeduren Zusammenfassung 5. Blöcke sind schachtelbare Anweisungen und bilden den Rahmen für die Lebensdauer lokaler Variablen. 6. Reihungen sind schachtelbare Objekte komplexen Typs; Zugriff nur über Referenzvariable. 7. Funktionen und Prozeduren werden stets als Klassenmethoden deklariert; bei Aufruf werden ihre Argumente immer als Wert übergeben. 8. Funktionsnamen können überladen werden; der Argumenttyp wird ggf. aufgeweitet. Σ