Kap.4: AUSDRÜCKE
Kapitel-Index
4.1 Elementare Ausdrücke
4.1.1 Namen
4.1.2 Primärausdruck
4.2 Operatoren, Prioritäten
4.2.1 Inkrement/Dekrement, präfix/postfix
4.2.2 Explizite Konvertierung (cast)
4.2.3 Ganzzahldivision und Rest
4.2.4 Bitweise arbeitende Operatoren
4.2.5 Bedingung
4.3 Java-Maschinen-Arithmetik
4.4 Testfragen
Ein Ausdruck (englisch Expression) ist eine Formel zur Berechnung eines Werts. Der Name FORTRAN (formula transmission) der ersten Programmiersprache zeigt bereits, welche Bedeutung Formeln für
Programmiersprachen haben. Ausdrücke setzen sich zusammen aus elementaren Ausdrücken (Konstanten, Variablen, Klammerungen) und Operationen mit Vorrangregeln.
------------------------------------------
VVVVVVVVVVV
Ausdruck (Prinzip, rekursive Definition)
VVVVVVVVVVV
VV
------------------------------------------
VV
VV VV
VV
Ein elementarer Ausdruck ist ein Ausdruck: VV
VV Konstante, z.B. 1 VV
VV Variable, z.B. x VV
VV Klammerung um Ausdrücke, z.B. (x-1), sin(x), a[4] VV
VV VV
VV
Eine Operation mit Ausdrücken ist ein Ausdruck: VV
VV unäre (monadische) Postfix-Operation, z.B. x++ VV
VV unäre (monadische) Präfix- Operation, z.B. -1 VV
VV binäre (dyadische) Infix- Operation, z.B. x-1 VV
VV VV
VV
Für die Berechnung von Ausdrücken gelten Vorrangregeln: VV
VV Elementarer Ausdruck höchster Vorrang, z.B. (1+2)*3== 9 VV
VV Operator-Vorrang nach Tabelle (4.2), z.B. 1+2 *3== 7 VV
VV dabei postfix Vorrang vor präfix, z.B. x=0; -x++ ==-1 VV
VV und unär Vorrang vor binär. z.B. -1-2 ==-3 VV
VV "Schriftreihenfolge" links vor rechts: VV
VV bei Operatoren gleichen Vorrangs, z.B. 8/4/2 == 1 VV
VV bei der Auswertung von Operanden, z.B. (++x) == x VV
VV Ausnahmen gegen die "Schriftreihenfolge": VV
VV präfix: rechts Vorrang vor links, z.B. x=0; -++x ==-1 VV
VV Zuweisung: rechts Vorrang vor links, z.B. (x=x=1)== 1 VV
VV VV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
z.B. mit Vereinbarung int i;
-------- prio 15 -------
-- prio 15 --
-15-
----15----
1 11 1 1 12 13 11 13 14 12 8 12
( (i=3) + (i*= i=2 ) ) * ( - 4 - - i --) / 9 == i / 2
---
----
i =i*(i=2)
-
-
----
-----
------
------
-
-
3 6 2 2
i==3 i==6 i==5 i==5
--------------------------
----------------------------
true
Die Prioritäten 1..14 der Operatoren (Syntax.036) und 15 der Separatoren (Syntax.037) sind in Abschnitt 4.2 aufgelistet. Zuweisungen, z.B. i=3, und allgemeine Zuweisungen, z.B. i*=7 bedeutet
i=i*7, werden in 5.1 erklärt. Krement-Operatoren, z.B. postfix --,
werden in 4.2.1 erklärt. Ganzzahldivision, z.B. 5/2 ergibt 2, wird
in 4.3.3 erklärt.
Der von uns gewählte Sammel-Begriff "elementarer Ausdruck" kann
ein Name (4.1.1) oder ein Primärausdruck (4.1.2) sein.
Ein Name ist nach Syntaxdiagramm 029 von der Form
029: Name Name
HHHHHHHHHHHHHHHHHHHHHHHHHHH
H QualifierPoint H
H
------- .
------
H
H
------------
H
H -
-
Identifier
-
-
H
H
------------
H
H H
HHHHHHHHHHHHHHHHHHHHHHHHHHH
und dient dazu, um ein/e
Paket , z.B. java.awt.event ,
Klasse , z.B. java.awt.event.WindowEvent ,
generischen Typ , z.B. T ,
Schnittstelle , z.B. java.awt.event.ActionListener ,
Mitglied , z.B. g.drawOval (Methode) ,
oder java.lang.Math.PI (Datenfeld),
Variable/Parameter , z.B. x ,
Sprungziel , z.B. loop ,
eindeutig zu vereinbaren. Der Qualifizierer-Punkt (QualifierPoint)
kann verschiedene Bedeutungen haben:
SuperPaket.SubPaket Datei-Separator (\ in Windows)
Superklasse.Subklasse Klassen-Erweiterung (extends)
Objekt.Mitglied oder
StaticKlasse.StaticMitglied Mitglied-Zugriff (member access)
Man beachte die Namenskonventionen 1.3.3 zur besseren Lesbarkeit
von Namen.
Ein Primärausdruck ist nach Syntaxdiagramm 042 von der Form
042: Primary PrimärAusdruck
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
H
------------
-
H
H -
-
( -
Expression
-
) -----------
H
H
------------
H
H
---------
H
H
-
Literal
------------------------
H
H
---------
H
H
------------
-
Class-
H
H
-
ResultType
-
. ---
class -----
-Literal
H
H
------------
-
H
H
enclosing instance
H
H
Class-
H
H
------
H
H
-
Name
-------
. -
Primary- H
H
------
- NoNew- H
H
invoked instance
Array H
H
---------------------
-
this ------
H
H
H
H
--------------------------------
H
H
-
ClassInstanceCreationExpression
-
H
H
--------------------------------
H
H
------------------
H
H
-
MethodInvocation
---------------
H
H
------------------
H
H
-------------
H
H
-
FieldAccess
--------------------
H
H
-------------
H
H
-------------
H
H
-
ArrayAccess
--------------------
H
H
-------------
-
H
H
-------------------------
H
H
-
ArrayCreationExpression
--------
-
H
H
-------------------------
H
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
Ein Literal ist eine Konstante. Zu den Literalen (Syntax.023)
zählen boolesche Werte (Syntax.009), Zeichen (Syntax.010), Zeichenketten (Syntax.011), Zahlen(Syntax.020/021), null (Syntax.022)
und zusätzlich Klassenliterale (Syntax.042). Ein Name oder ein
Access (siehe Reihung 6.1, Datenfeld 9.1.1 und this 9.1.2) ist
genau dann eine Konstante, wenn er als final vereinbart wurde,
sonst eine (nonfinal) Variable.
Wie das Syntaxdiagramm und die nachfolgenden Beispiele zeigen,
muss eine "Klammerung", d.h. eine Zusammenfassung mit höchstem
Vorrang, nicht notwendig eine Einschließung in "normale" Klammern
(...) sein,
z.B. (x+7) "normale" Klammerung
new int[x+7] new-Reihung (6.3)
Math.sqrt(x+7) Methoden-Aufruf (7.1.2)
new Point(x+7,x-7) Klasseninstanz-Erzeugungsausdruck (9.1.1)
4.2 Operatoren, Separatoren, Prioritäten
In den folgenden Tabellen sind die Operatoren (Syntax.036) und
Separatoren (Syntax.037) aufgelistet mit Angabe der Prioritäten.
036: Operator Operator
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
H one of H
H new see Keyword prio15 Allocator H
H ++ PostfixIncrementOp prio14 -
-
H
H -- PostfixDecrementOp prio14 -
Postfix-
-Crement- H
H ++ PrefixIncrementOp prio13 -
Operator
OperatorH
H -- PrefixDecrementOp prio13
-
H
H ~ BitwiseComplementOp prio13
H
H ! LogicalNotOp prio13
-PrefixOperator H
H + UnaryPlusOp prio13
H
H - UnaryMinusOp prio13 -
H
H (Type) prio13 CastOperator H
H see Separator H
H * MultiplicationOp prio12 -
H
H / DivisionOp prio12
-Multiplicative- H
H % RemainderOp prio12 -
Operator H
H + AdditionResp- prio11 -
H
H ConcatenationOp
-AdditiveOperator H
H - SubtractionOp prio11 -
H
H << BitwiseShiftLeftOp prio10 -
H
H >> BitwiseShiftRight- prio10
H
H SameSignOp
-ShiftOperator H
H >>> BitwiseShiftRight- prio10
H
H ZeroSignOp -
H
H < LessThanOp prio 9 -
H
H <= LessThanOrEqualOp prio 9
-NumericalComparison- H
H > GreaterThanOp prio 9
Operator H
H >= GreaterThanOrEqualOp prio 9 -
H
H instanceof prio 9 TypeComparisonOperator H
H see Keyword H
H == EqualOp prio 8 -
EqualityOperator H
H != NotEqualOp prio 8 -
H
H & BitwiseRespLogicalAndOp prio 7 -
BitwiseRespLogical- H
H ^ BitwiseRespLog.NotEqualOp prio 6
- Operator H
H | BitwiseRespLogicalOrOp prio 5 -
H
H && ShortCircuitLogicalAndOp prio 4 -
ShortCircuit- H
H || ShortCircuitLogicalOrOp prio 3 -
LogicalOperator H
H ? ThenOp prio 2 -
H
H : ElseOp prio 2 -
ConditionalOperator H
H = SimpleAssignmentOp prio 1 -
H
H *= MultiplicationAssignmentOp prio 1
H
H /= DivisionAssignmentOp prio 1
H
H %= RemainderAssignmentOp prio 1
H
H += AdditionRespConcatenation- prio 1
H
H AssignmentOp
H
H -= SubtractionAssignmentOp prio 1
H
H <<= BitwiseShiftLeft- prio 1
H
H AssignmentOp
-AssignmentOperator H
H >>= BitwiseShiftRight- prio 1
H
H SameSignAssignmentOp
H
H >>>= BitwiseShiftRight- prio 1
H
H ZeroSignAssignmentOp
H
H &= BitwiseRespLogical- prio 1
H
H AndAssignmentOp
H
H ^= BitwiseRespLogical- prio 1
H
H NotEqualAssignmentOp
H
H |= BitwiseRespLogical- prio 1
H
H OrAssignmentOp -
H
H An operator with greater num- Ein Operator mit grösserer H
H ber has higher priority. Nummer hat höhere Priorität. H
H Operator(s) with priority 3 to Operator(en) mit Prioritäten 3 H
H 12 are evaluated left to right bis 12 werden von links nach H
H and - if of same priority - rechts ausgewertet und - falls H
H associated left to right. von gleicher Priorität - von H
H links nach rechts assoziiert. H
H ConditionalOperator(s) and As- BedingterOperator(en) und Zu- H
H signmentOperator(s) are asso- weisungsOperator(en) werden H
H ciated right to left. von rechts nach links assozi- H
H ziiert. H
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
037: Separator Separator
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
H one of . Point H
H , Comma H
H ; Semicolon H
H ( ) Parantheses H
H [ ] Brackets H
H { } Braces H
H < > AngleBrackets H
H Separator(s) have highest pri- Separator(en) haben höchste H
H ority 15. Priorität 15. H
H Constructs with Separator(s) . Konstrukte mit Separator(en) . H
H or , or ; are evaluated and oder , oder ; werden von H
H associated left to right. links nach rechts ausgewertet H
H und assoziiert. H
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
Die Syntax ist als kontextfreie Grammatik nicht in der Lage, die
Prioritäten von Operatoren und Separatoren direkt zu erfassen. Für
jede Priorität muss ein neues Diagramm eingeführt werden. Die aufsteigende Folge der Diagramme Syntax.043-059 entspricht der absteigenden Folge der Prioritäten 14-1.
4.2.1 Inkrement/Dekrement, präfix/postfix
Inkrement-Operator ++ und Dekrement-Operator -- , zusammenfassend
Krement genannt, gibt es sowohl vorangestellt (präfix) als auch
nachgesetzt (postfix), z.B.
präfix ++i oder --i
postfix i++ oder i--
Diese Operatoren können nur speziell auf Variablen, nicht allgemein auf Ausdrücke, angewandt werden. Ihr Ergebnis ist ein Ausdruck, aber keine Variable mehr.
Sie berechnen den "Nachfolger" bzw. "Vorgänger" einer numerischen
Variablen (NumericType, 2), d.h. vereinfacht erklärt, sie addieren
/subtrahieren eine dem Variablen-Typ entsprechende 1 auf den Wert
der Variablen.
Die Inkrementierung/Dekrementierung der Variablen selbst ist ein
Seiteneffekt der Krementierungs-Operation.
---------------------------------------
VVVVVV
Präfix- und Postfix-Krement (Prinzip)
VVVVVV
VV
---------------------------------------
VV
VV VV
VV
Das Ergebnis eines Präfix- Krements ist der VV
VV neue Wert der Variablen nach Krementierung. VV
VV VV
VV z.B. int i=1;out.print(++i+" "+i); // 2 2 VV
VV int i=1;out.print(--i+" "+i); // 0 0 VV
VV VV
VV
Das Ergebnis eines Postfix-Krements ist der VV
VV alte Wert der Variablen vor Krementierung. VV
VV VV
VV z.B. int i=1;out.print(i+++" "+i); // 1 2 VV
VV int i=1;out.print(i--+" "+i); // 1 0 VV
VV VV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
Obwohl eine Krement-Operation vereinfacht als additive Operation
mit anschließendem Assignment erklärt wird, z.B. wird ++x durch
x=x+1 erkärt, sind doch Unterschiede zu beachten,
z.B. int i=0;int[] a={0,3,5};out.print( ++a[++i] ); // 4
int i=0;int[] a={0,3,5};out.print(a[++i]=a[++i]+1); // 6
char c='c'; out.print(++c); // d
char c='c'; out.print(c=(char)(c+1)); // d
char c='c'; out.print(c=c+1); // Typ-Fehler
Vorteil unärer Krement-Operationen vor binären additiven Operationen ist die erheblich kürzere Ausführungszeit.
4.2.2 Explizite Konvertierung (cast)
In Kapitel 2 wurde bereits eine Übersicht über Typen (2) und
implizite Konvertierung (2.1) gegeben. Darüber hinaus kann der
Programmierer selbst explizit konvertieren, allerdings nur primitive Typen in primitive Typen (PrimitiveTypeCast) und Referenztypen in Referenztypen (ReferenceTypeCast).
Explizite Konvertierung, englisch cast ("werfen auf", "umformen"), ist nach Syntaxdiagramm 044 von der Form
044: CastExpression KonvertierungsAusdruck
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
H H
H
--------------------------------
H
H
H
H
-------------
------------------
H
H -
-
( -
ReferenceType
-----
) -
-
PostfixExpression
-
H
H
-------------
------------------
H
H
-
NotPlus-
H
H
-
~ -
- Minus-
H
H
-
! -
Prefix-
H
H
------
-
Operator
H
H
-------------
-----------------
H
H
-
( -
PrimitiveType
-
-
) -
-
UnaryExpression
--
-
H
H
-------------
-----------------
H
H
-----------
-
H
H
-
[ -
] -
H
H H
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
z.B. (int)3.14 PrimitiveTypeCast
(int[])temperature ReferenceTypeCast
(MyClass)myObject "
Wird ein Gleitpunktzahltyp explizit konvertiert in einen Ganzzahltyp, werden alle Ziffern nach dem Dezimalpunkt abgeschnitten.
-----------------------------------------
(int)x
2 BBBBB
1 BBBBB
-3.0 -2.0 -1.0
--
----
----
BBBBBBBBB
----
----
-
x
1.0 2.0 3.0
BBBBB -1
BBBBB -2
-----------------------------------------
Fig.4.2.2: "Abschneiden" mit (int)x
z.B. (int)-1.7 == -1 , (int)0.7 == 0 , (int)1.7 == 1
Wie das Syntaxdiagramm Syntax.044 und die Beispiele zeigen, ist
ein Cast nur der "Operator" vor dem "Operanden".
Das nachfolgende Programm Roulette benutzt den Pseudo-Zufallszahlen-Generator random() aus java.lang.Math und konvertiert die mit
37 multiplizierten Zufallszahlen zwischen 0.0 und 1.0 (ausschließlich 1) in Roulette-Zahlen zwischen 0 und 36 (einschließlich 36).
//************************* Roulette.java ************************
// Roulette als random()-Pseudo-Zufallszahlenfolge *
// mit Bestimmung der Haeufigkeiten (frequencies). *
// Command: java Roulette LENG CASTS *
//****************************************************************
// java.lang. Object
import static java.lang.System .out; // ||`System
import static java.lang.Integer.parseInt; // |`Integer
import static java.lang.Math .random; // `Math
class Roulette
{public static void main(String[] args) //args[0],args[1] genutzt
{final int LENG =parseInt(args[0]),
CASTS=parseInt(args[1]);
int[] freq =new int[LENG];
for(int cast=0;cast<CASTS;cast++)
{final int ROUL=(int)(LENG*random());
freq[ROUL]+=1;
out.printf("%1d ",ROUL);
}
out.println();
out.println();
for(int i=0;i<LENG;i++)
{out.printf("%1$3d:%2$4d",i,freq[i]);
if (i%7==6)
{out.println();}
}
}
}
//****************************************************************
Command
----------------------
java Roulette 37 37000
Output, random() abhaengig
-----------------------------------------------------------
31 23 12 23 22 18 15 31 2 29 ... 13 3 28 17 4 30 2 35 14 36
0: 989 1:1021 2:1024 3:1035 4:1020 5:1018 6: 990
7: 985 8: 978 9:1063 10:1006 11:1031 12:1046 13:1016
14: 951 15: 997 16: 977 17:1005 18:1038 19:1008 20: 906
21: 949 22: 941 23:1043 24: 993 25:1027 26: 972 27: 972
28:1011 29:1016 30: 992 31: 999 32:1027 33:1014 34: 994
35: 942 36:1004
4.2.3 Ganzzahldivision und Rest
Die Ganzzahldivision (integral division) a/b , d.h. die Division im Spezialfall von Ganzzahltyp (IntegralType, 2) Operanden, und
den (Divisions-) Rest (remainder) a%b erklärt man am besten in Abhängigkeit:
-------------------------------------
VVVVVVVVVVVVV
Ganzzahldivision und Rest (Prinzip)
VVVVVVVVVVVVVV
VV
-------------------------------------
VV
VV VV
VV Das Ergebnis der Ganzzahldivision a/b ist der ganzzahlige VV
VV Quotient aus den ganzzahligen Operanden a und b. VV
VV Ziffern nach dem Dezimalpunkt werden abgeschnitten. VV
VV VV
VV z.B. 2006/100 ergibt 20 VV
VV VV
VV Das Ergebnis des (Ganzzahldivisions-) Rests a%b ist der VV
VV Rest des ersten Operanden bei der Division a/b. VV
VV VV
VV z.B 2006%100 ergibt 6 VV
VV VV
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
z.B. 2006/100 * 100 + 2006%100 ergibt 2006
Die folgende Figur zeigt den Verlauf der Rest-Funktion a%b im
Spezialfall b=3. Man erkennt den "modularen" Verlauf
0%3 == 0 1%3 == 1 2%3 == 2
3%3 == 0 4%3 == 1 5%3 == 2
6%3 == 0 7%3 == 1 8%3 == 2 usw.
im positiven und negativen Bereich, vergleichbar mit der Modul
-Funktion a mod b in der Mathematik.
----------------------------------------
a%3
2 B B
1 B B
-5 -4 -3 -2 -1
--
--
--B--
--
--B--
--
--B--
--
--
a
1 2 3 4 5
B B-1
B B -2
----------------------------------------
Fig. 4.2.3: (Ganzzahldivisions-) Rest a%3
Der Rest-Operator % ist auch für Gleitpunktzahl-Operanden zugelassen,
z.B. out.print( 7.7%3.3); // 1.1
Die Verwendung des gleichen Operatorzeichens / für Ganzzahl- und
Gleitpunktzahl-Division erfordert erhöhte Aufmerksamkeit vom Programmierer, der die Operanden-Typen streng beachten muss, z.B.
1 /2 ergibt 0
1.0/2.0 oder 1.0/2 oder 1/2.0 ergibt 0.5
4.2.4 Bitweise arbeitende Operatoren
Die im Syntaxdiagramm Syntax.036 für Operatoren (siehe oben 4.2)
aufgelisteten bitweise arbeitenden Operatoren werden im folgenden
Beispiel Bitwise speziell für Operanden vom Typ int vorgeführt.
//************************ Bitwise.java **************************
// Bitweise arbeitende Operatoren *
// Command: java Bitwise x y *
//****************************************************************
class Bitwise
{static void printBitwise(String s,int i)
{int masc= Integer.MIN_VALUE;
System.out.print (s);
for(int bit=32;bit>0;bit--)
{System.out.print ((masc&i)==0?0:1);
masc>>>=1;
}
System.out.println();
}
public static void main(String[] args) // args ungenutzt
{int x= Integer.parseInt(args[0]),
y= Integer.parseInt(args[1]);
printBitwise(" Integer.MIN_VALUE=", Integer.MIN_VALUE);
printBitwise("-Integer.MAX_VALUE=",-Integer.MAX_VALUE);
printBitwise(" -2=", -2);
printBitwise(" -1=", -1);
printBitwise(" 0=", 0);
printBitwise(" +1=", +1);
printBitwise(" +2=", +2);
printBitwise(" Integer.MAX_VALUE=", Integer.MAX_VALUE);
printBitwise(" x=", x);
printBitwise(" ~x=", ~x);
printBitwise(" x<<1=", x<<1);
printBitwise(" x>>1=", x>>1);
printBitwise(" x>>>1=", x>>>1);
printBitwise(" y=", y);
printBitwise(" x&y=", x&y);
printBitwise(" x|y=", x|y);
printBitwise(" x^y=", x^y);
}
}
//****************************************************************
Command
-------------------
java Bitwise -3 -4
Output
---------------------------------------------------
Integer.MIN_VALUE=10000000000000000000000000000000
-Integer.MAX_VALUE=10000000000000000000000000000001
-2=11111111111111111111111111111110
-1=11111111111111111111111111111111
0=00000000000000000000000000000000
+1=00000000000000000000000000000001
+2=00000000000000000000000000000010
Integer.MAX_VALUE=01111111111111111111111111111111
x=11111111111111111111111111111101
-x=00000000000000000000000000000011
~x=00000000000000000000000000000010
x<<1=11111111111111111111111111111010
x>>1=11111111111111111111111111111110
x>>>1=01111111111111111111111111111110
y=11111111111111111111111111111100
x&y=11111111111111111111111111111100
x|y=11111111111111111111111111111101
x^y=00000000000000000000000000000001
Bitweise arbeitende Operatoren erlauben die gezielte Änderung
eines oder mehrerer Bits, den Vergleich von Bits und mit Masken
-Technik auch die Abfrage von Bits, vgl. masc im obigen Programm
Bitwise. Sie haben IntegralType Operanden und liefern ein Ergebnis
vom Typ int, wenn jedoch ein Operand vom Typ long ist, ein Ergebnis vom Typ long. Ein ShiftOperator hat nur einen Operanden. Ist
dieser vom Typ int, dann werden nur die rechten 5 Bits der Verschiebung (0..31) verwendet; ist dieser vom Typ long, dann werden
nur die rechten 6 Bits der Verschiebung (0..63) verwendet.
Die den logischen Operatoren ! && != || ähnlichen bitweisen
Operatoren ~ & ^ | können auch auf boolean Operanden angewandt
werden und liefern dann wie die logischen Operatoren ein Ergebnis
vom Typ boolean. Allerdings werden bei den bitweisen Operatoren &
und | stets beide Operanden berechnet, bei den logischen Operatoren && und || der rechte Operand nur dann, wenn das Ergebnis nicht
bereits durch den linken Operanden bestimmt werden kann (short
circuit).
Eine Bedingung ist nach Syntaxdiagramm 056 von der Form
056: Condition Bedingung
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
H H
H boolean or Boolean nonvoid H
H
-------------
nonvoid
------------
H
H
ShortCircuit-
ThenOp
----------
ElseOp
Conditional-
H
H -
LogicalOr-
-
? ---
Expression
-
: --
Expression
-
H
H
Expresion
----------
------------
H
H
-------------
H
H H
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
z.B. int i=25,j=10;out.print( i>j ? i-=j : j-=i ); // 15
Je nachdem, ob der Wert des ersten Ausdrucks (ShortircuitLogicalOrExpression) true oder false ist, wird nur der Wert des zweiten Ausdrucks (Expression) nach dem ThenOp ? oder nur der Wert
des dritten Ausdrucks (ConditionalExpression) nach dem ElseOp :
berechnet. Der erste Ausdruck muss vom Typ boolean oder Boolean
sein. Entweder müssen die beiden folgenden Ausdrücke vom gleichen
Typ sein oder der speziellere Typ muss "numerisch ohne Verlust
oder erweiternd zum nächsten Gleitpunktzahl-Wert" (implizite Konvertierung 2.1) in den allgemeineren Typ konvertierbar sein. Der
allgemeinere Typ ist der Ergebnistyp.
In der Syntax fehlen Klammern um die Bedingung, die der Autor in
diesem Buch setzt, um unübersichtliche Konstruktionen mit "open
-end-festival" zu vermeiden, falls nicht bereits Klammern gesetzt
sind, z.B. in 4.2.4 durch System.out.print(...) .
Die Syntax schränkt den ersten Ausdruck auf ShortCircuitLogicalOrExpression mit Vorrang>=3 ein, was besagt, dass hier nicht wieder eine Condition (Vorrang 2) und kein Assignment (Vorrang 1)
stehen darf. Ausserdem schränkt die Syntax den dritten Ausdruck
auf ConditionalExpression mit Vorrang>=2 ein, was besagt, dass
hier wieder eine Condition (Vorrang 2, Abarbeitung von rechts nach
links), aber kein Assignment (Vorrang 1) stehen darf.
Bedingte Ausdrücke sind ähnlich wie if-Anweisungen (5.2.1) aufgebaut, z.B. ist obiges Beispiel vergleichbar mit
int i=25,j=10;if(i>j){out.print(i-=j);}else{out.print(j-=i);}//15
Aber bei bedingten Ausdrücken kann es keine Kurzform ohne
ElseOp : geben, da die Condition auch unter der Bedingung false
einen Wert liefern muss.
4.3 Java-Maschinen-Arithmetik
Die virtuelle Java-Maschine ist eine 32-Bit-Maschine, d.h. Ganzzahlen vom Typ int und Gleitpunktzahlen vom Typ float belegen ein
Maschinenwort mit 32 Bit und doppelt genaue Ganzzahlen vom Typ
long und doppelt genaue Gleitpunktzahlen vom Typ double belegen
zwei Maschinenworte mit insgesamt 64 Bit.
Ganzzahl-Arithmetik ist Dualzahlen-Arithmetik mit Zweierkomplement ~1=-2 (siehe Bitwise 4.2.4), modular im Bereich des betreffenden Typs int oder long. Wenn ein Ganzzahlwert den Bereich seines Typs int oder long verläßt, wird er reduziert modulo des Bereichs,
z.B. out.print(Integer.MAX_VALUE+1); // -2147483648
Es gibt keine Fehlermeldungen für Überlauf bei der GanzzahlArithmetik, ausgenommen Division durch 0 oder Rest durch 0, die
unzulässig sind und eine ArithmeticException auswerfen, z.B.
z.B. int i=0;
try {out.print(1/i);}
catch(ArithmeticException e) {out.print("1/0");}
try {out.print(1%i);}
catch(ArithmeticException e) {out.print("1%0");}
In der virtuellen Java-Maschine ist Ganzzahl-Aritmetik als int/
long-Arithmetik implementiert. byte/char/short-Arithmetik ist implizit int-Arithmetik.
Java-Gleitpunktzahl-Arithmetik ist eine Untermenge der EEE 754
-1985 Standard-Gleitpunktzahl-Arithmetik.
Es gibt keine Fehlermeldungen für Überlauf bei der Gleitpunktzahl-Arithmetik, auch nicht bei Division durch Null oder Rest
durch Null. Es wird dann mit Pseudo-Unendlich POSITIVE_INFINITY
oder NEGATIVE_INFINITY oder mit der Pseudo-Nichtzahl NaN ('not
a number') weitergerechnet, die in den zu float/double gehörigen
Klassen Float/Double vereinbart sind, z.B.
out.print( 1.0/0.0==Double.POSITIVE_INFINITY); // true
out.print( 1.0/0.0); // Infinity
out.print(-1.0/0.0); // -Infinity
out.print( 0.0/0.0); // NaN
out.print( 1.0%0.0); // NaN
Pseudo-Unendlich POSITIVE_INFINITY, NEGATIVE_INFINITY und
Pseudo-Nichtzahl NaN in der Gleitpunktzahl-Arithmetik sind vergleichbar mit Pseudo-Zeiger null in der Zeiger-Arithmetik (6.2,
9.1.1, 9.2.1).
zu Frage
abdeckbare Antwort
---------------------------------------------
--------------------
4.1 Ist eine Operation ein elementarer
nein
Ausdruck?
4.2.1 Welche der folgenden sind korrekte
Ausdrücke (Expression) und was ist
dann das Ergebnis?
keiner:
++1
1 keine Variable
++x++
x++ keine Variable
alle:
+-1
-1
1+-1
0
4.2.2 Welche der folgenden sind korrekte
explizite Konvertierungen (cast) und
was ist dann das Ergebnis?
(boolean)1
keine:
(int)true
alle:
(char)99.9
c
(double)(int)3.14
3.0
4.2.3 Was ist das Ergebnis?
3/9.0
0.3333333
3/9
0
3%9
3
4.2.3 Was ist das Ergebnis?
9.9%5.5%3.3
1.1
4.2.4 Welche der folgenden sind korrekte
bitweise Operationen und was ist dann
das Ergebnis?
keine:
1.0<<1
1 <<1.0
alle:
1 << -1
-2147483648
(char)('A'|'B')
C
4.2.4 Schreibe das Programm Bitwise um
bit=32 ->bit=64
vom Typ int auf den Typ long.
Integer ->Long
int ->long
getint()->getlong()
4.2.5 Was ist das Ergebnis?
( 0==1 ? 2==3 : 4==5 )
false
( 0 <1 ? 2 <3 : 4 <5 )
true
4.3 Was ist das Ergebnis?
-Double.POSITIVE_INFINITY
Double.NEGATIVE_
INFINITY
Double.POSITIVE_INFINITY/
NaN
Double.NEGATIVE_INFINITY
Math.sqrt(-1)
NaN