Java Programmierung
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.


4.1      Elementare Ausdrücke

  Der von uns gewählte Sammel-Begriff "elementarer Ausdruck" kann ein Name (4.1.1) oder ein Primärausdruck (4.1.2) sein.


4.1.1    Namen

  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.


4.1.2    Primärausdruck

  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   v       ,-------------,          |  ,------------------,     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).


4.2.5    Bedingung

  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).




4.4      Testfragen     

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
                                             |
    Java Programmierung
  Kap.05