Java Programmierung
Kap.7:   METHODEN


Kapitel-Index
   7.1   Methoden-Vereinbarung (ggf. generisch)       
   7.2   Methoden-Aufruf      
   7.3   Rekursive Methoden     
   7.4   Parameterübergabe (by value)     
   7.4.1    Nur-Eingabe über PrimitiveType-Parameter     
   7.4.2    Ein/Ausgabe über ReferenceType-Parameter     
   7.5   Überladen (overloading) von Methoden     
   7.6   Ergebnistyp und Rücksprung (return)     
   7.7   Hauptprogramm mit main, Argumente     
   7.8   Testfragen     
  Methoden sind Mitglieder von Klassen (9.1.1). Eine Methode ist ein Unterprogramm (subprogram) mit Parametern bei der Methoden -Vereinbarung (7.1) und entsprechenden Argumenten beim Methoden -Aufruf (7.2).
                     ,----------------------,
  VVVVVVVVVVVVVVVVVVV| Methoden (Übersicht) |VVVVVVVVVVVVVVVVVVV
  VV                 '----------------------'                 VV
  VV Man unterteilt Methoden in                               VV
  VV                                                          VV
  VV  # nonvoid Methoden, d.h.                                VV
  VV                                                          VV
  VV     Funktionen vom Ergebnistyp Type (mit Ergebnis),      VV
  VV     die einen Ergebniswert berechnen und                 VV
  VV     aufgerufen werden als Ausdruck, z.B. sin(x)          VV
  VV                                                          VV
  VV  # void Methoden, d.h.                                   VV
  VV                                                          VV
  VV     Prozeduren vom Ergebnistyp void (ohne Ergebniswert), VV
  VV     die nur eine Tätigkeit ausführen und                 VV
  VV     aufgerufen werden als Anweisung, z.B. out.print(x);  VV
  VV                                                          VV
  VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV

  Auch Operationen (4.2.) sind Unterprogramme. Sie sind aber nicht als Methoden in Klassen vereinbart, sondern in der Sprache vordefiniert, und können in Java nicht vom Programmierer vereinbart werden.


7.1      Methoden-Vereinbarung (ggf. generisch)

  Zu einer Methoden-Vereinbarung kann es mehrere Methoden-Aufrufe (7.2) geben. Vereinbarungen mit generischen Typ-Parametern (siehe Beispiel Generic 9.2.2) oder mit rekursivem (7.3) Methoden-Aufruf oder mit Überladen (7.5) des Methoden-Bezeichners sind zulässig.
  Eine Methoden-Vereinbarung (MethodDeclaration) ist nach Syntaxdiagramm 083 (hier Erweiterung 083° durch Einsetzen von MethodDeclarator Syntax.081) von der Form
083°:MethodDeclaration            MethodenVereinbarung           
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
H   ,---------------------,                                      H
H   |  ,----------------, |                                      H
H ->+->| MethodModifier |-'                                      H 
H   |  '----------------'                                        H
H   v                                ,---------------------,     H
H   |------------------------------->| TypeParameterClause |-,   H 
H   |                                '---------------------' |   H
H   |                                  of generic method     |   H
H   v                                                        |   H
H   |--------------------------------------------------------'   H
H   |                                                            H
H   |                  Method-                                   H
H   |  ,----------,  ,------------,  ,-----------------------,   H
H   '->|ResultType|->| Identifier |->| FormalParameterClause |-, H
H      '----------'  '------------'  '-----------------------' | H
H                                      of method               | H
H                                                              | H
H                 ,--------------------------------------------' H
H                 |                                              H
H                 |                    MethodBody                H
H                 |  ,--------,      ,-------,                   H
H                 |->| Throws |----->| Block |--->               H
H                 |  '--------' ^ |  '-------' |                 H
H                 |             | |            |                 H
H                 '-------------' '----> ; ----'                 H
H                                abstract or native              H
H                                                                H
H An   AbstractMethodDeclaration  Eine AbstraktMethodenVereinba- H
H is  a  MethodDeclaration  with  rung  ist eine MethodenVerein- H
H AbstractMethodModifier(s)  and  barung  mit  AbstraktMethoden- H
H Semicolon  instead  of Method-  Modifizierer(n)  und Semikolon H
H Body.                           anstatt MethodenRumpf.         H
H                                                                H
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH

 z.B. double ariMed(double a,double b){return (a+b)/2;}
  Eine Methode kann als Mitglied einer Klasse (siehe 9.1.1) auf vielfältige Weise modifiziert werden (MethodModifier Syntax.070),
 z.B. static double ariMed(double a,double b){return (a+b)/2;}  .
  Werden Parameter einer Methode als final modifiziert, so bedeutet das nicht, dass nur Konstanten als aktuelle Parameter eingesetzt werden dürfen, sondern dass die Parameter im Methoden-Rumpf konstant bleiben,
z.B. double ariMed(final double a,final double b){return (a+b)/2;}

  Eine Methode kann vereinbart werden ggf. generisch mit einer Typ-Parameter-Klausel, mit einem Ergebnistyp ggf. generisch mit einer Typ-Variablen, mit einem Methoden-Bezeichner und mit einer leeren oder nichtleeren Formalparameter-Klausel ggf. generisch mit Typ-Variablen,
  z.B. (siehe Generic 9.2.2)

       <S> void swap(S[] s){S memo=s[0];s[0]=s[1];s[1]=memo;}   .
  Eine Methode kann Ausnahmen auswerfen (Throws Syntax.082,11.1.1),
  z.B. static double geoMed(double a,double b)
                   throws    RuntimeException
        {if(a*b<0){throw new RuntimeException(a+"*"+b+"<0");}
         return sqrt(a*b);}                                      ,
und besitzt einen Methoden-Rumpf oder im Falle einer abstrakten Methode (9.1.4, 9.2) oder einer plattformabhängigen (native) Methode an Stelle des Methoden-Rumpfs ein Semikolon,
  z.B. abstract int hebSteuer(int einkommen);                    .

7.2      Methoden-Aufruf


  Eine Methode wird aufgerufen, indem vom Ort des Aufrufs zum Ort der Vereinbarung gesprungen wird, nachdem vorher die Argumente, und die Rücksprungadresse übergeben worden sind. Nach Durchlaufen des Methoden-Rumpfs wird zur Rücksprungadresse an den Ort des Aufrufs zurückgesprungen, nachdem ggf. bei einer Funktion (nonvoid method) der Ergebniswert zurückübergeben (return, 7.6) wurde.

  Ein Methoden-Aufruf (siehe unten) kann ggf. qualifiziert werden mit dem Namen einer Klasse. Aufgerufen werden kann ggf. generisch mit einer Typ-Argument-Klausel. Es folgt ein Methoden-Bezeichner und eine leere oder nicht leere Argument-Klausel,
  z.B. (siehe Generic 9.2.2)
       this.<T>swap(t);

  Wurde eine Methode vereinbart, die Ausnahmen auswirft (Throws

  Syntax.082, 11.1.1), dann muss die ausgeworfene Ausnahme beim

  Methoden-Aufruf abgefangen werden,
  z.B. try                     // geoMed(double,double) siehe 7.1
        {out.println("geoMed(-5,20)="+geoMed(-5,20));}
       catch(RuntimeException e)           
        {err.println(e.toString());}
                           // java.lang.RuntimeException: -5*20<0

  Ein Methoden-Aufruf (syntaktisch MethodInvocation) ist nach Syntaxdiagramm 085 von der Form
085: MethodInvocation             MethodenAufruf
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
H                                                                H
H          Class-                                                H
H        ,------,                                                H
H ------>| Name |-----> . ----,                                  H
H  |     '------'             |                                  H
H  |                          |                                  H
H  |       Class-             |                                  H
H  |     ,------,             |                                  H
H  |->-->| Name |-----> . -,  |                                  H
H  |  v  '------'          |  |                                  H
H  |  |--------------------'  |                                  H
H  |  |                       |                                  H
H  |  '--> super -----> . -,  |                                  H
H  |       class           |  |                                  H
H  |                       |  |                                  H
H  |     ,---------,       |  |  ,---------------------------,   H            
H  |---->| Primary |--> . -+->-->| NonWildTypeArgumentClause |-, H  
H  |     '---------'       |     '---------------------------' | H
H  |      e.g. this        |       of generic method           | H
H  |                       v                                   | H
H  |  ,--------------------------------------------------------' H
H  |  |    Method-                                               H
H  |  |  ,------------,                                          H
H  |  '->| Identifier |----,                                     H
H  |     '------------'    |                                     H
H  |       Method-         |                                     H
H  |     ,------,          |     ,----------------,              H
H  '---->| Name |--------------->| ArgumentClause |->            H
H        '------'                '----------------'              H
H                                  of method                     H
H                                                                H
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH

  z.B. ariMed(-5,20) // 7.5       ariMED(double,double) siehe 7.1
7.3      Rekursive Methoden

  Rekursive Aufrufe von Methoden in ihrer eigenen Vereinbarung (direkt) oder wechselseitig in der anderen Vereinbarung (indirekt) sind zulässig. Unendliche Folgen von Aufrufen werden durch Setzen von Abbruch-Prüfungen vermieden,
  z.B. static void MergeSort(int L,int R)  // MergeSort siehe 6.4
        { ...
         if (L  <M) {MergeSort(alt(L  ),alt(M));}
         if (M+2<R) {MergeSort(alt(M+2),alt(R));}
          ...
        }                                                        .
  Es wird stets nur ein Exemplar der Methode vom Compiler vorgehalten. Lediglich die jeweiligen aktuellen Parameter und die Rücksprungadresse werden in einem Gedächtnis gekellert.
  In modernen Compilern ist die Parameterübergabe und Sprung-Kellerung so effizient implementiert, dass Methoden in rekursiver Version und in repetiver Version etwa gleiche Laufzeiten ergeben.
//********************** Sum.java ********************************
//  Summe ueber 5000 Glieder: sqrt(random())+...+sqrt(random())  *
//             rekursiv oder mit for-Schleife                    *
//****************************************************************
//            java.lang.                                 Object
import static java.lang.System.*;                      // |`System
import static java.lang.Math.*;                        // `Math

class Sum
 {static double recSum(int length)
   {return     (length==0 ? 0 : recSum(length-1)+sqrt(random()));
   }
  static double forSum(int length)
   {double      sum=0;
    for(int     i=0;i<length;i++) {sum+=sqrt(random());}
    return      sum;
   }
  public static void main(String[] args)         // args ungenutzt
   {long        ms=currentTimeMillis();
    out.print  ("recSum="+recSum(5000)+" ms=");
    out.println(currentTimeMillis()-ms);
                ms=currentTimeMillis();
    out.print  ("forSum="+forSum(5000)+" ms=");
    out.println(currentTimeMillis()-ms);
   }
 }

//****************************************************************

| Output
+-------------------------------
|recSum=3331.9981175605744 ms=10 
|forSum=3323.2189966095066 ms=10 

7.4      Parameterübergabe (by value)


  Die Parameter einer Methoden-Vereinbarung (7.1) nennt man "formale Parameter", synonym "Parameter", die Parameter eines Methoden -Aufrufs (7.2) "aktuelle Parameter", synonym "Argumente". Die Parameter und Argumente einer Methode müssen in Anzahl, Anordnung und Typ zueinander passen, brauchen jedoch nicht in ihren Namen übereinzustimmen. Mit final-Modifizierer sind Parameter Konstanten im Methoden-Rumpf, sonst Variablen. Ihre zugehörigen Argumente können beliebige Ausdrücke sein.

  Eine formale Parameter-Klausel kann auch Mehrfach-Parameter enthalten, die durch Auslassung (ellipsis) "..." gekennzeichnet werden (Syntax.076), z.B. (Format-String, 2.7)
          String format(String format_string,Object... args)

  Zu Beginn des Methoden-Aufrufs wird der Wert jedes Arguments an den entsprechenden Parameter in Kopie übergeben (pass by value). Am Ende des Methoden-Aufrufs erfolgt keine Rück-Kopierung von Parameterwerten, d.h. die Argumente sind vor Überschreibung durch die entsprechenden Parameter geschützt.


7.4.1    Nur-Eingabe über PrimitiveType-Parameter

  Über Grundtyp-Parameter (PrimitiveType Syntax.030, 2) ist nur Eingabe, aber keine Ausgabe möglich.
//*************************** GGT.java ***************************
// Groesster gemeinsamer Teiler von zwei pos. Zahlen nach Euklid.*
//  Demonstration der Nur-Eingabe ueber PrimitiveType-Parameter. *
//              Command: java GGT args[0] args[1]                *
//****************************************************************
//            java.lang.                                 Object
import static java.lang.System.out;                    // |`System
import static java.lang.Integer.parseInt;              // `Integer

class GGT 
 {static int findGGT(int a,int b)         // a,b vom PrimitiveType
   {while      (a!=b) if(a>b) {a-=b;} else {b-=a;}
    return      a;
   }
  public static void main(String[] args) //args[0],args[1] genutzt
   {out.println(findGGT(parseInt(args[0]),parseInt(args[1]))+
                  "=GGT("       +args[0]  + "," +  args[1]+")");
   }
 }

//****************************************************************
                                             Nur-Eingabe der Werte
                                                             args
                                                            ,----,
                                                        ,---+4711|
| Command                                    a          v   '----'      
+---------------                     Adr.2:,----, Adr.4711:,-----,
|java GGT 66 385                           | 66<+----------+-"66"| 
                                           '----'  parseInt|     |
                                             b             |-----|
| Output                             Adr.9:,----,          |     |
+--------------                            |385<+----------+"385"| 
|11=GGT(66,385)                            '----'  parseInt'-----'
                                           Keine Ausgabe der Werte
  Im obigen Programm GGT wird der größte gemeinsame Teiler zweier positiver Zahlen nach dem Reduktionsverfahren von Euklid (3.Jh.v. Chr.) durch forlaufende Subtraktion bestimmt:
    "Da jeder Teiler von  a,b  auch Teiler von  a-b  und b-a ist,
    reduziert man das Problem im Falle a>b auf die Bestimmung des
    größten gemeinsamen Teilers von  a-b,b  und im Falle von  b>a
    auf die Bestimmung des größten gemeinsamen Teilers von a,b-a.
    Gilt  für das neue Zahlenpaar  a==b , so ist a oder b der ge-
    suchte größte gemeinsame Teiler, sonst wird weiter reduziert.

    Bei  jeder  Reduktion  nähern sich die beiden Zahlen  a,b  um
    mindestens 1,  d.h.  die  Reduktion führt nach endlich vielen
    Schritten zum Ziel  a==b ."

7.4.2    Ein/Ausgabe über ReferenceType-Parameter


  Über Referenztyp-Parameter (RefereceType Syntax.0.30, 2) ist zwar auch nur Eingabe einer Adresse möglich, keine Ausgabe einer Adresse, aber der Wert, auf den diese Adresse zeigt, kann verändert werden, was einen Ausgabe-Effekt ergibt. Der Parameter und das zugrhörige Argument, müssen vom gleichen Referenztyp sein. Für den Ausgabe-Effekt muss das Argument speziell eine Variable sein und nicht, wie sonst zulässig, ein allgemeiner Ausdruck.

  Es folgt das Beispiel Tausch mit formalem Parameter String[] paar und entsprechendem aktuellen Parameter String[] args.
//************************* Tausch.java **************************
//   Vertauschen der Werte der Komponenten einer Paar-Reihung.   *
//  Demonstration der Ein/Ausgabe ueber ReferenceType-Parameter. *
//             Command: java Tausch args[0] args[1]              *
//****************************************************************

//            java.lang                                   Object
import static java.lang.System.out;                     // `System

class Tausch 
 {
  static void tausch(String[] paar)      // paar vom ReferenceType
   {
    final String MEMO=paar[0];paar[0]=paar[1];paar[1]=MEMO;
   }
  public static void main(String[] args) //args[0],args[1] genutzt
   {
    tausch      (args);                  // args vom ReferenceType
    out.println (args[0]+" "+args[1]);     
   }
 }

//****************************************************************
                                   Nur-Eingabe der Adresse
| Command                           paar           args
+---------------------       Adr.2:,----,   Adr.7:,----,
|java Tausch Dick Doof             |4711<---------+4711| 
                                   '----'         '----'
                                      '-------------'             
| Output                                     v  ,-------------,
+---------                             Adr.4711:|"Dick"|"Doof"|
|Doof Dick                                      '-------------' 
                                             Ein/Ausgabe der Werte
  Ein Zahlen-Tausch void tausch(double[] paar) wäre auch ohne Hilfsspeicher MEMO möglich,
  z.B. für paar[0]>=paar[1]>=0:
       paar[0]-=paar[1];paar[1]+=paar[0];paar[0]=paar[1]-paar[0];












7.5      Überladen (overloading) von Methoden


  Der Bezeichner einer Methode sowie die Anzahl, Anordnung und Typen der Parameter einer Methode bilden die "Signatur" der Methode. Die Bezeichner der Parameter und der Ergebnistyp der Methode gehören nicht zur Signatur der Methode.


  Methoden können hinsichtlich ihres Bezeichners "überladen" sein (overloading), d.h. den gleichen Bezeichner besitzen, sofern sie sich in der übrigen Signatur, d.h. bezüglich der Anzahl, Anordnung und Typen ihrer Parameter, unterscheiden.

  Im nachfolgenden Programm Overloading bestimmt der Typ des aktuellen Parameters von overload(), welche der verschiedenen überladenen Methoden mit dem gleichen Bezeichner overload aufgerufen wird. Als Argumente werden Null-Werte (siehe DefaultNullValue Syntax.039), eingegeben.
//*********************** Overloading.java ***********************
//    Demonstration des Ueberladens einer Methode overload(p).   *
//        Die Parameter p sind von 6 verschiedenen Typen.        *
//  Die Argumente sind 13 NullWerte von 10 verschiedenen Typen.  *
//****************************************************************
class Overloading
 {static String           overload(boolean p) {return("boolean");}
  static String           overload(char    p) {return("char   ");}
  static String           overload(int     p) {return("int    ");}
  static String           overload(double  p) {return("double ");}
  static String           overload(String  p) {return("String ");}
  static String           overload(char[]  p) {return("char[] ");}

  public static void main(String[] args)         // args ungenutzt
   {System.out.println(
    "          false -> "+overload(           false)+"\r\n"
   +"   (char)   0   -> "+overload(   (char)    0  )+"\r\n"
   +"           '0'  -> "+overload(            '0' )+"\r\n"
   +"   (byte)   0   -> "+overload(   (byte)    0  )+"\r\n"
   +"   (short)  0   -> "+overload(   (short)   0  )+"\r\n"
   +"            0   -> "+overload(             0  )+"\r\n"
   +"   (long)   0   -> "+overload(   (long)    0  )+"\r\n"
   +"   (float)  0.0 -> "+overload(   (float)   0.0)+"\r\n"
   +"            0.0 -> "+overload(             0.0)+"\r\n"
   +"   (String)null -> "+overload(   (String) null)+"\r\n"
 +"            \"\"  -> "+overload(             "" )+"\r\n"
   +"   (char[])null -> "+overload(   (char[]) null)+"\r\n"
   +"new char[]{'0'} -> "+overload(new char[] {'0'})+"\r\n");
   }
 }
//****************************************************************
 
| Output                 
+--------------------------
|          false -> boolean
|   (char)   0   -> char     ISOControl NUL mit der Nummer 0
|           '0'  -> char     Zeichen '0' mit der Nummer 48
|   (byte)   0   -> int      kein Parameter byte  p, aber int p
|   (short)  0   -> int      kein Parameter short p, aber int p
|            0   -> int    
|   (long)   0   -> double   kein Parameter long  p, aber double p
|   (float)  0.0 -> double   kein Parameter float p, aber double p
|            0.0 -> double 
|   (String)null -> String   null vom ReferenceType String
|            ""  -> String   Zeichenkette der Länge 0
|   (char[])null -> char[]   null vom ReferenceType char[]
|new char[]{'0'} -> char[]   1-dim.Reihung mit 1 Komponente '0'
  In Kapitel 2 wurde unter "Implizite Konvertierung" bereits das Prinzip des minimalen Aufwands beim Overloading formuliert:
         ,----------------------------------------------,
 VVVVVVVV| Minimaler Aufwand beim Overloading (Prinzip) |VVVVVVVV
 VV      '----------------------------------------------'      VV
 VV                                                            VV
 VV  Wenn mehrere Methoden bezüglich ihrer Parametertypen als  VV
 VV  "numerisch verlustfrei  konvertierbar  oder zum nächsten  VV
 VV  Gleitpunktzahl-Wert erweiterbar"  in Frage kommen,  wird  VV
 VV  diejenige ausgewählt, die den geringsten Konvertierungs-  VV
 VV  aufwand (siehe "Grundtypen und String" Kap.2) erfordert.  VV
 VV                                                            VV
 VV   z.B. int i=9;double d;d=Math.sqrt(i);           // d=3.0 VV
 VV                                                            VV
 VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
  Im Programm Overloading fehlen overload(byte), overload(short), overload(long) und overload(float). Für (byte)0 und (short)0 wird ersatzweise overload(int) ausgewählt. Für (long)0 und (float)0 wird ersatzweise overload(double) ausgewählt.


7.6      Ergebnistyp und Rücksprung (return)


  Für die Übergabe des Funktionswertes und für den anschließenden Rücksprung zum Ort des Funktions-Aufrufs (7.2) ist die return-Anweisung vorgesehen. Als strukturierter Sprung wurde die return-Anweisung bereits in 5.4.2 behandelt.
  Eine Methode vom Ergebnistyp Type (nonvoid), d.h. eine Funktion (7), muss am Ende ihres Methoden-Rumpfs eine return-Anweisung mit Type Expression besitzen. In ihrem Methoden-Rumpf kann es weitere return-Anweisungen mit Type Expression geben. Eine Methode vom Ergebnistyp void, d.h. eine Prozedur (7), z.B. main(), kann in ihrem Methoden-Rumpf return-Anweisungen ohne Expression besitzen. Im Falle von Prozeduren wirkt auch das Erreichen des Endes des Methoden-Rumpfs wie eine return-Anweisung.

7.7      Hauptprogramm mit main, Argumente


  Die (Haupt-) Methode main(String[] args) ist vom Ergebnistyp void, d.h. eine Prozedur (7), die in einer (Haupt-) Klasse, z.B. MyMainClass, vereinbart wird und aufgerufen wird mit dem Kommando
               java MyMainClass                                 .
  Um (public) aufrufbar im Paket der Vereinbarung der Klasse MyMainClass zu sein, bzw. im aktuellen Vereichnis (default-Paket), und um (static) instantiiert zu werden ohne dynamische Vereinbarung eines Objekts von MyMainClass im Programm, muss main modifiziert werden (MethodModifier Syntax.070) als
               public static void main(String[] args)           .
  Dem Parameter String[] args von main() können beim Aufruf von main() Werte zugewiesen werden, z.B.
               java MyMainClass  "mit" "Argumenten"             
   (entspricht args=new String[]{"mit","Argumenten"};)          . 
  Gänsefüßchen um die String-Literale können fortgelassen werden, z.B.
               java MyMainClass mit Argumenten                  .
  Die Länge der entstandenen Reihung args kann mit args.length abgefragt werden, hier args.length==2 .

  Da es ausser dem Konstruktor für void main(String[] args) keinen Konstruktor für void main() gibt, muss args auch dann vereinbart werden, wenn args nicht genutzt wird. Zu Testzwecken kann der Programmierer auch in Applets ( 13.3 ) zunächst eine Methode main(String[] args) vereinbaren.



7.8      Testfragen

zu    Frage                                    |abdeckbare Antwort
-----------------------------------------------+------------------
                                               |
7        Wie  heißt  der Ergebnistyp,  mit dem | void
      eine Prozedur-Vereinbarung beginnt?      |
                                               |
7/7.1  Kann der Funktionswert ein Zeiger sein, | ja
      d.h. vom Referenztyp?                    |
                                               |
7/7.1  Können Funktionen neben ihrem Ergebnis- | ja
      Wert auch Seiteneffekte haben,  wie z.B. |
      Fehler-Ausdrucke  oder globale Zuweisun- |
      gen?                                     |
                                               |
7.2     Wie findet das Programm nach einem Me- | beim     Ansprung
      thoden-Aufruf,  d.h.  einem Ansprung des | wird   die  Rück-
      Unterprogramms,  zurück zur betreffenden | sprung-   Adresse
      Aufruf-Stelle, da es mehrere geben kann? | dem Unterprogramm
                                               | mitgeteilt.
                                               |
7.3   class LoreLey     // indirekte Rekursion |
       {                                       |
        static void Lore(String s) //ruft Ley  |
         {if(!s.equals("Lore")) {Ley (s);}     |
          else {System.out.print(s+" ");}}     |
        static void Ley (String s) //ruft Lore |
         {if(!s.equals("Ley" )) {Lore(s);}     |
          else {System.out.print(s+" ");}}     |
        public static void main(String[] args) |
         {for(String each:args) {Lore(each);}} |
       }                                       |
                                               |
        Was ergeben die folgenden Kommandos?   |
          java LoreLey                         |
          java LoreLey Lore                    |Lore
          java LoreLey Ley                     |Ley
          java LoreLey Lore Ley                |Lore Ley
          java LoreLey LoreLey                 |StackOverflowError
                                               |
7.4     Gibt es in Java eine Parameterübergabe | nein (leider)
      ähnlich dem 'pass by name' in  ALGOL_60, |
      d.h.  inline-Einsetzen des Parameters in |
      Ausdrücke ohne sofortige Berechnung des  |
      Ausdrucks?                               | 
                                               |
7.4.1    Ersetze in GGT                        |
      die   "mehrmalige Subtraktion a-=b"      | if(a>b) {a%=b;}
      durch "einmalige  Restbildung a%=b" .    | else    {b%=a;}     
                                               |  
7.4.2    Ist 'pass by reference' in  C++  ver- | ja im Effekt, 
      gleichbar mit Ein/Ausgabe über Reference-|  aber reference
      Type Parameter in Java?                  |  ist alias in C++
2.1/7.5  Muß beim Überladen die aufrufende Me- | nein, implizite
      thode genau die gleiche Signatur aufwei- |  Konvertierung 
      sen wie die aufgerufene Methode?         |  möglich
                                               |
7.6    Kann im Methoden-Rumpf von main stehen: |
      # eine return-Anweisung ohne Expression? | ja
      # eine return-Anweisung mit  Expression? | nein
                                               |
7.7     Schreibe  ein  Programm Echo,  das den |
      letzten Argument-String des java-Komman- |
      dos ausgibt, z.B.                        |
      java Echo Bürgermeister von W E_S_E_L    | E_S_E_L
                                               |
    Java Programmierung
  Kap.08