Programmieren in Java: Einführung


Kapitel 4: Funktionen


Inhaltsverzeichnis

Dieses Buch ist unter einer Creative Commons-Lizenz lizensiert.


4.1 Methoden

Befehle zusammenfassen

Eine Funktion ist eine Zusammenstellung mehrerer Befehle. Anstatt in einem Programm jeden Befehl einzeln aufzurufen, wenn er benötigt wird, kann eine entsprechende Funktion aufgerufen werden, die die auszuführenden Befehle enthält. Bei einem Aufruf der Funktion werden alle in ihr zusammengefassten Befehle schrittweise ausgeführt, so als wären sie jeweils einzeln aufgerufen worden.

In Java gibt es genaugenommen keine Funktionen, sondern nur Methoden. Eine Methode ist nichts anderes als eine Funktion, die zu einer Klasse gehört. In Java müssen alle Funktionen zu Klassen gehören - es darf keine Funktionen außerhalb von Klassen geben. Insofern gibt es in Java nur Methoden und keine Funktionen. Während objektorientierte Programmierer also sprachlich Funktionen und Methoden unterscheiden, gibt es in technischer Hinsicht jedoch keinen Unterschied. Nachdem es in Java nur Methoden gibt, wird in diesem Buch ab sofort auch nur mehr von Methoden und nicht mehr von Funktionen gesprochen.

import java.applet.*; 
import java.awt.*; 

public class MyApplet extends Applet 
{ 
  public void init() 
  { 
    showStatus("Hallo, Welt!"); 
    setBackground(Color.blue); 
  } 
} 

Sie haben bereits mehrere Methoden kennengelernt: Die Methode init() wird für Java-Applets immer dann aufgerufen, wenn der Browser das Java-Applet zum ersten Mal lädt. Wenn Sie beim Laden des Applets zum Beispiel in der Statusleiste des Browsers den Text "Hallo, Welt!" anzeigen möchten und außerdem die Hintergrundfarbe des Applets auf Blau setzen möchten, so müssen Sie einfach die beiden entsprechenden Anweisungen wie oben in die Methode init() setzen. Beim Aufruf von init() durch den Browser werden alle Anweisungen innerhalb der Methode nacheinander ausgeführt. Es wird also zuerst der Text der Statusleiste gesetzt und danach die Hintergrundfarbe im Applet. Dies geschieht über die beiden Methoden showStatus() und setBackground().


4.2 Methodendefinition

Erster Schritt: Methode erstellen

Wie werden Methoden definiert? Erstmal ist wichtig, dass Sie Methodendefinitionen immer innerhalb von Klassen schreiben. Methoden müssen per Definition zu einer Klasse gehören und müssen daher auch innerhalb der beiden geschweiften Klammern der Klasse stehen.

import java.applet.*; 

public class MyApplet extends Applet 
{ 
  public void init() 
  { 
  } 

  public void start() 
  { 
  } 

  public void stop() 
  { 
  } 

  public void destroy() 
  { 
  } 
} 

Vier für Java-Applets wichtige Methoden haben Sie bereits kennengelernt. Eine Methodendefinition beginnt jeweils mit einem Zugriffsattribut. Zugriffsattribute legen fest, inwiefern andere Klassen Zugriff auf die Methode haben. Zugriffsattribute haben Sie bereits kurz im Zusammenhang mit Klassen kennengelernt. Es handelt sich tatsächlich jedesmal um die gleichen Zugriffsattribute. Sie können also mit Zugriffsattributen festlegen, inwiefern andere Klassen auf die eigene Klasse und auf Methoden in der Klasse zugreifen können. Darüberhinaus können Zugriffsattribute auch auf Eigenschaften angewandt werden. Wie dieser Mechanismus genau funktioniert, lernen Sie im Kapitel 5, Zugriffsattribute kennen.

Nach dem Zugriffsattribut folgt der Rückgabewert der Methode. Der Rückgabewert der Methode ist entweder ein primitiver Datentyp (boolean, char, byte, short, int, long, float oder double), eine Klasse aus einer Klassenhierarchie, eine selber programmierte Klasse oder aber das spezielle Schlüsselwort void. Der Datentyp legt fest, welche Art von Information von der Methode als Ergebnis zurückgegeben wird. Es kann sich hierbei also um einen primitiven Datentyp handeln, es kann sich um ein Objekt vom Typ einer Klasse handeln oder aber um void. void bedeutet, dass die Methode überhaupt kein Ergebnis zurückgibt. Methoden müssen also nicht unbedingt Ergebnisse zurückgeben.

In Java ist es wie auch in C# oder C++ nicht möglich, mehr als einen Rückgabewert von einer Methode zu erhalten. Methoden geben also genau einen oder keinen Rückgabewert zurück.

Hinter dem Datentyp des Rückgabewertes wird der Methodenname angegeben. Sie können hier einen beliebigen Namen verwenden, der jedoch möglichst aussagekräftig sein sollte und darauf hinweisen sollte, was die Methode eigentlich macht. Methodennamen wie start() und stop() sind gute Beispiele.

Achten Sie darauf, dass es Methodennamen gibt, die eine spezielle Bedeutung haben. Wenn Sie Ihre Methode init() nennen, wird diese Methode automatisch aufgerufen, wenn der Browser Ihr Applet lädt. Wollen Sie hingegen verhindern, dass Ihre Methode als Event-Handler agiert und bei Eintreten bestimmter Ereignisse aufgerufen wird, müssen Sie der Methode einen anderen Namen geben.

Hinter dem Methodennamen folgt die Parameterliste. Eine Parameterliste wird hierbei immer in runden Klammern angegeben. Selbst wenn keine Parameterliste angegeben wird, müssen die runden Klammern geschrieben werden - sie sind dann eben leer. Dies ist der Fall bei den bereits kennengelernten vier speziellen Methoden von Applets.

Was sind Parameter? Parameter sind Variablen - egal, ob von primitiven Datentypen oder Referenzvariablen - die als eine Art Eingabe an die Methode übergeben werden. Die Methode nimmt die übergebenen Variablen entgegen und arbeitet mit diesen innerhalb der Methode.

So wie Methoden also als Ergebnis einen Wert zurückgeben können, können sie Parameter als Eingabewerte erhalten. Im Gegensatz zum Rückgabewert kann eine Methode auch mehrere Parameter erwarten.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    int x = 5; 
    int y = 10; 
    int result = add(x, y); 
    System.out.print(result); 
  } 

  public static int add(int a, int b) 
  { 
    int r = a + b; 
    return r; 
  } 
} 

In obiger Java-Application ist eine Methode namens add() definiert. Der Methodenname ist so gewählt, dass sich gleich erkennen läßt, was diese Methode tut: Sie führt Additionen durch.

Die Methode add() ist so definiert, dass sie einen Wert vom Typ int zurückgibt. Außerdem ist eine Parameterliste angegeben: Die Methode add() erwartet zwei Parameter, die beide vom Typ int sind. Parameterlisten sehen so aus, dass Variablendefinitionen zwischen den beiden runden Klammern angegeben werden. Mehrere Variablendefinitionen werden hierbei durch Kommata getrennt. In diesem Fall besteht also die Parameterliste der Methode add() aus den beiden Variablen a und b, die beide vom Typ int sind.

Die Definition von add() besagt nun folgendes: Bei Aufruf der Methode müssen genau zwei Werte oder Variablen übergeben werden, die beide vom Typ int sind. Als Ergebnis liefert add() einen Wert zurück, der ebenfalls vom Typ int ist.

Wie ist add() definiert, was geschieht innerhalb der Methode? Die beiden Parameter, die die Methode erhält, werden mit dem Operator + addiert. Das Ergebnis der Addition wird in einer lokalen Variablen r gespeichert, die ebenfalls vom Typ int ist. In der nächsten Zeile wird mit Hilfe des Schlüsselwortes return die Methode beendet und gleichzeitig ein Wert oder eine Variable zurückgegeben. Der Wert oder die Variable muß hierbei hinter return angegeben werden. In diesem Fall wird also die Variable r als Ergebnis zurückgegeben.

Das Ganze nochmal mit dem gebührenden Abstand betrachtet: Die Methode add() erwartet zwei Werte, die addiert werden. Das Ergebnis der Addition wird dann von der Methode add() zurückgegeben. Die Methode add() ermöglicht also die Addition zweier Zahlen - genauer: zweier Werte vom Typ int.

Das, was Sie bisher kennengelernt haben, nennt man Methodendefinition. Eine Methodendefinition ist immer der erste Schritt, der notwendig ist, bevor die Methode benutzt werden kann. Eine Methodendefinition besteht wie eben gesehen aus einem Methodenkopf - Rückgabewert, Methodenname und Parameterliste - und dem Methodenrumpf. Als Methodenrumpf wird der Anweisungsblock bezeichnet, der durch die geschweiften Klammern begrenzt wird und hinter dem Methodenkopf steht.

Sinn und Zweck des Schlüsselworts static im Methodenkopf von add() wird am Ende dieses Kapitels erklärt. An dieser Stelle können Sie static einfach ignorieren.


4.3 Methodenaufruf

Zweiter Schritt: Methode einsetzen

Die Definition der Methode add() war der erste Schritt. Wie wird diese Methode nun tatsächlich benutzt und eingesetzt?

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    int x = 5; 
    int y = 10; 
    int result = add(x, y); 
    System.out.print(result); 
  } 

  public static int add(int a, int b) 
  { 
    int r = a + b; 
    return r; 
  } 
} 

Der Aufruf einer Methode erfolgt dadurch, dass der Methodenname gefolgt von zwei runden Klammern angegeben wird. Je nach Definition der Methode müssen ein oder mehrere Parameter zwischen die runden Klammern gesetzt werden. add() ist so definiert, dass zwei Parameter vom Typ int erwartet werden. Deswegen müssen beim Aufruf von add() auch zwei int-Variablen übergeben werden. Dies geschieht, indem die Namen der zu übergebenen Variablen durch Kommata getrennt in die runden Klammern gesetzt werden. In diesem Fall werden also die beiden lokalen Variablen x und y an die Methode add() übergeben.

Was passiert nun in diesem Programm? Wenn die Java-Application gestartet wird, wird automatisch die Methode main() aufgerufen. In dieser Methode werden zwei Variablen vom Typ int definiert, die einmal auf den Wert 5 und einmal auf den Wert 10 gesetzt werden. Danach wird die Methode add() aufgerufen. Die Definition von add() sieht so aus, dass zwei Parameter vom Typ int erwartet werden. Daher werden in den runden Klammern beim Aufruf von add() die beiden Variablen x und y angegeben.

Jetzt geschieht folgendes: Der Wert der Variablen x - nämlich 5 - wird in die Variable a hinüberkopiert. Der Wert der Variablen y - nämlich 10 - wird in die Variable b kopiert. Welcher Wert wohin kopiert wird, hängt davon ab, an welcher Stelle die Variablen angegeben sind. x ist die erste Variable beim Aufruf von add(). Der erste Parameter in der Definition von add() ist a. Daher wird der Wert von x nach a kopiert. Für die Variable y und den Parameter b erfolgt der Kopiervorgang entsprechend.

Wichtig ist: Beim Methodenaufruf werden die übergebenen Werte kopiert. Die Methode add() arbeitet nicht mit den Original-Variablen x und y, sondern nur mit Kopien. Dieses Konzept heißt call by value. Parameter werden in Java bei Methodenaufrufen immer als Kopie übergeben, als Wert, nicht als Original-Variable selber.

Der Rückgabewert von add() wird in einer Variablen result gespeichert. Diese Variable wird mit Hilfe der Klasse java.lang.System, die Zugriff auf Standardfunktionen des Computers ermöglicht, auf den Bildschirm ausgegeben. java.lang.System bietet unter anderem über out Zugriff auf die Standardausgabe an. out ist eine Referenzvariable, eine statische Eigenschaft der Klasse java.lang.System. Indem hinter out der Zugriffsoperator . angeben wird, kann unter anderem auf eine Methode print() zugegriffen werden. Der Wert oder die Variable, die als Parameter an die Methode print() übergeben wird, wird auf den Bildschirm ausgeben.


4.4 Umgang mit Methoden optimieren

Methodenaufrufe verschachteln

Die grundlegenden Dinge, die Sie beim Einsatz von Methoden beachten müssen, kennen Sie nun: Zuerst müssen Sie Methoden definieren, und dann können Sie sie aufrufen. Darüberhinaus gibt es jedoch ein paar Tricks, die den Umgang mit Methoden vereinfachen können. Gleichzeitig verdeutlichen Ihnen die folgenden Beispiele den Einsatz von Methoden.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    int x = 5; 
    int y = 10; 
    System.out.print(add(x, y)); 
  } 

  public static int add(int a, int b) 
  { 
    int r = a + b; 
    return r; 
  } 
} 

Die Beispiel-Application wurde nun modifiziert. Der Aufruf von add() findet nun zwischen den runden Klammern der Methode print() statt. Die Variable result, die vorher den Rückgabewert von add() entgegennahm, wurde gestrichen.

Was passiert nun im Programm? Sie sehen hier einen verschachtelten Methodenaufruf. Die Methode add() wird in den runden Klammern von print() aufgerufen. Java geht bei verschachtelten Methodenaufrufen so vor, dass innere Methodenaufrufe zuerst ausgeführt werden. Das heißt, es wird zuerst die Methode add() ausgeführt, dann die Methode print().

Der Methode add() werden wieder die zwei Variablen x und y übergeben, deren Werte in die Parameter a und b hinüberkopiert werden. Wenn add() zu Ende gerechnet hat und das Ergebnis der Addition mit return zurückliefert, dann wird nun dieser Rückgabewert von add() nicht in einer Variablen gespeichert, sondern direkt zwischen den runden Klammern als Übergabewert an die Methode print() weitergereicht.

Durch verschachtelte Methodenaufrufe können Sie sich also die Definition von Variablen sparen. Anstatt in einer Variable das Ergebnis eines Methodenaufrufes zu speichern und dann diese Variable im nächsten Schritt als Parameter an eine andere Methode weiterzugeben, rufen Sie einfach an der Stelle die Methode auf, an der der Rückgabewert der Methode als Parameter an eine andere Methode übergeben werden soll. Der Rückgabewert der einen Methode wird direkt als Übergabewert an die andere Methode weitergereicht, ohne ihn zwischenzeitlich in einer Variablen zu speichern.

Die Beispiel-Application lässt sich noch an anderer Stelle vereinfachen.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    int x = 5; 
    int y = 10; 
    System.out.print(add(x, y)); 
  } 

  public static int add(int a, int b) 
  { 
    return a + b; 
  } 
} 

Anstatt in der Methode add() die Summe der Parameter a und b in einer neuen Variablen zu speichern und dann diese Variable mit return zurückzugeben, kann direkt hinter return die Addition durchgeführt werden. Das Ergebnis dieser Addition wird nun nicht mehr in einer Variablen gespeichert, sondern direkt mit return als Rückgabewert der Methode add() weitergegeben.

Eine weitere Code-Reduzierung könnte wie folgt aussehen.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    System.out.print(add(5, 10)); 
  } 

  public static int add(int a, int b) 
  { 
    return a + b; 
  } 
} 

Nun werden die Zahlenwerte 5 und 10 nicht mehr in zwei Variablen x und y gespeichert, die dann ihrerseits als Parameter an die Methode add() übergeben werden, sondern 5 und 10 sind direkt zwischen die Klammern von add() gesetzt worden. Auch diese Schreibweise ist völlig okay. Die beiden Zahlenwerte werden wie üblich in die Parameter a und b der Methode add() kopiert, in der dann mit diesen kopierten Werten weitergerechnet wird.


4.5 Fremde Methoden

Aufruf von Methoden anderer Klassen

Betrachten Sie das Beispiel von eben nochmal ganz genau.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    System.out.print(add(5, 10)); 
  } 

  public static int add(int a, int b) 
  { 
    return a + b; 
  } 
} 

In diesem Beispiel werden zwei Methoden aufgerufen, nämlich add() und print(). Während add() jedoch einfach über Angabe des Methodennamens aufgerufen werden kann, muss vor den Methodenaufruf von print() zusätzlich System.out angegeben werden. Wieso ist eine derartige zusätzliche Angabe bei print() notwendig, bei add() anscheinend aber nicht?

Methoden, die wie add() in der gleichen Klasse definiert sind, können grundsätzlich einfach über den Methodennamen aufgerufen werden. Die Methode print() ist jedoch nicht in der Klasse MyApplication definiert. Sie liegt in einer fremden Klasse - nämlich auf der, auf der System.out basiert. Sie müssen daher, um auf print() zugreifen zu können, diesem Methodenaufruf System.out voranstellen.

Sehen Sie sich folgendes Beispiel an, das zu Beginn dieses Kapitels kurz vorgestellt wurde.

import java.applet.*; 
import java.awt.*; 

public class MyApplet extends Applet 
{ 
  public void init() 
  { 
    showStatus("Hallo, Welt!"); 
    setBackground(Color.blue); 
  } 
} 

In diesem Fall wird keine Application erstellt, sondern ein Applet. Wie bei Applets üblich muss die entsprechende Klasse, hier MyApplet, von java.applet.Applet abgeleitet und ihr untergeordnet werden.

In der Methode init() werden zwei Methoden showStatus() und setBackground() aufgerufen. Weder die eine noch die andere Methode ist wie Sie sehen in der Klasse MyApplet definiert. Dennoch können beiden Methoden direkt über Angabe des Methodennamens aufgerufen werden, ohne dass eine zusätzliche Angabe vor den Methodennamen notwendig ist. Wie ist das möglich?

Die Klasse MyApplet wird der Elternklasse java.applet.Applet untergeordnet. Diese Unterordnung hat den Zweck, dass die Klasse MyApplet die Funktionalität der Elternklasse java.applet.Applet erbt. In der Elternklasse java.applet.Applet befinden sich die Definitionen der beiden Methoden showStatus() und setBackground(). Indem MyApplet sich der Klasse java.applet.Applet unterordnet, erbt sie sämtliche Methodendefinition dieser Elternklasse. Das heißt, die Methodendefinitionen stehen direkt in der Kindklasse MyApplet zur Verfügung, so als wären sie dort von Ihnen angegeben worden. Daraus folgt, dass Sie die Methoden direkt über den Methodennamen aufrufen können, ohne zusätzliche Angaben vornehmen zu müssen.

Anhand dieses Beispiels sehen Sie bereits einen großen Vorteil der Vererbung: Durch Vererbung können Methoden, die in einer Elternklasse definiert sind, geerbt werden und stehen in der Kindklasse zur Verfügung, ohne dass der Programmierer auch nur irgendeine dieser geerbten Methoden selber entwickeln muss.

Genaugenommen definiert übrigens die Klasse java.applet.Applet keine Methode setBackground(). Während die Methode showStatus() tatsächlich direkt in der Klasse java.applet.Applet angegeben ist, ist setBackground() in einer Elternklasse von java.applet.Applet definiert. Durch Vererbung wird setBackground() an die Klasse java.applet.Applet weitergegeben und kommt schließlich auch in der Klasse MyApplet an.


4.6 Methoden überladen

Gleicher Methodenname, unterschiedliche Parameter

Unter Überladen versteht man die Definition mehrerer Methoden, die sich darin unterscheiden, dass sie unterschiedlich viele Parameter bzw. Parameter mit unterschiedlichen Typen erwarten.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    System.out.print(add(5, 10, 15)); 
  } 

  public static int add(int a, int b) 
  { 
    return a + b; 
  } 

  public static int add(int a, int b, int c) 
  { 
    return a + b + c; 
  } 
} 

Nun sind in der Java-Application zwei Methoden definiert, die beide add() heißen. Solange sich die Parameterlisten unterscheiden, ist dies auch kein Problem. In dem einen Fall erwartet add() genau zwei Parameter vom Typ int, im anderen Fall genau drei Parameter vom Typ int. Welche Methode also jeweils aufgerufen wird, hängt nicht nur vom Methodennamen ab, sondern auch von der Anzahl der Parameter. Im obigen Beispiel wird die Methode aufgerufen, die drei Parameter erwartet - es werden beim Aufruf schließlich drei Zahlen angegeben.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    System.out.print(add(5.2, 10.3)); 
  } 

  public static int add(int a, int b) 
  { 
    return a + b; 
  } 

  public static double add(double a, double b) 
  { 
    return a + b; 
  } 
} 

Nun werden in der Anwendung zwei Methoden add() definiert, die sich nicht in der Anzahl der Parameter unterscheiden, sondern im Datentyp der Parameter. Diesmal erwartet die zweite Methode add() als Parameter zwei Werte vom Typ double. Beim Methodenaufruf werden die Kommazahlen 5.2 und 10.3 übergeben. Beachten Sie, dass Kommazahlen mit einem Punkt geschrieben werden. Diese Kommazahlen werden in die Parameter a und b der Methode add() kopiert, die als Parameter Kommazahlen erwartet. Auch diese Methode führt eine Addition aus und gibt die Summe der Kommazahlen als Ergebnis zurück.

Das Überladen von Methoden funktioniert also auf zwei Wegen: Entweder besitzen die Methoden eine unterschiedliche Anzahl an Parametern. Oder aber die Parameter der Methoden unterscheiden sich im Datentyp. Ein Überladen von Methoden allein über unterschiedliche Datentypen des Rückgabewertes ist in Java nicht möglich.

Sie kennen überladene Methoden übrigens schon aus einem anderen Beispiel.

import java.applet.*; 
import java.awt.*; 

public class MyApplet extends Applet 
{ 
  String Text = new String("Hallo, Welt!"); 

  public void paint(Graphics g) 
  { 
    g.drawString(Text, 0, 10); 
  } 
} 

Beim Erzeugen von Objekten muss hinter dem Schlüsselwort new die Klasse angegeben werden, von der ein Objekt erzeugt werden soll. Genaugenommen wird nicht die Klasse angegeben, sondern ein Konstruktor - also eine Methode, die genauso heißt wie die Klasse. Konstruktoren können Parameter übergeben werden. So ist es beispielsweise möglich, ein Objekt vom Typ java.lang.String mit einer bestimmten Zeichenkette zu initialisieren, indem die Zeichenkette als Parameter an den Konstruktor übergeben wird. Übergibt man an den Konstruktor von java.lang.String keine Zeichenkette, wird ein neues Objekt erstellt, das nicht initialisiert ist.

String Text1 = new String(); 
String Text2 = new String("Hallo, Welt!"); 

Während in der ersten Zeile ein Objekt vom Typ String erstellt wird, indem der Standardkonstruktor aufgerufen wird - also der Konstruktor, der keinen Parameter erwartet - wird in der zweiten Zeile ein Objekt vom Typ String über einen Konstruktoraufruf erstellt, der genau einen Parameter in Form einer Zeichenkette erwartet. Die Referenzvariable Text1 verweist auf ein Objekt, das leer ist. Die Referenzvariable Text2 verweist auf ein Objekt, in dem die Zeichenkette "Hallo, Welt!" liegt.

Hier sehen Sie nochmal ganz deutlich eine Überladung: Gleicher Methodenname, unterschiedliche Anzahl an Parametern. Es handelt sich jedesmal um einen Konstruktor - also um eine Methode, die genauso heißt wie die Klasse. Das eine Mal bekommt sie jedoch einen Parameter übergeben, das andere Mal nicht.

Fast alle Klassen aus der offiziellen Java-Klassenhierarchie bieten überladene Konstruktoren an. Sie können also Objekte, die Sie erstellen, auf vielfältige Art und Weise initialisieren, indem Sie unterschiedlich viele Parameter oder aber Parameter von unterschiedlichen Typen an Konstruktoren übergeben. Was möglich ist und was nicht hängt natürlich von jeder Klassendefinition ab. Sie müssen also auch hier wieder in der Dokumentation nachschlagen, um herauszufinden, welche Konstruktoren von der jeweiligen Klasse angeboten werden und was Sie an Parametern übergeben können.


4.7 Statische Methoden

Methoden ohne Objekte

Kennen Sie noch den Unterschied zwischen Instanz- und Klassenvariablen? Instanzvariablen existieren innerhalb von Objekten, Klassenvariablen gehören zu Klassen und werden von allen Objekten einer Klasse geteilt. Zusätzlich kann auf Klassenvariablen über den nun bereits bekannten Zugriffsoperator . auch ohne Objekte zugegriffen werden. Das Schlüsselwort static hat aus Instanzvariablen Klassenvariablen gemacht.

Das Schlüsselwort static kann auch auf Methoden angewandt werden - und hat dort genau den gleichen Effekt wie bei Variablen. Eine Methode, die mit static definiert ist, nennt man Klassenmethode. Ebenso wie bei Klassenvariablen kann auf Klassenmethoden zugegriffen werden, ohne dass ein Objekt benötigt wird. Sie hatten bereits eine Klassenmethode aktiv eingesetzt.

public class MyApplication 
{ 
  public static void main(String[] args) 
  { 
    System.out.print("Hallo, Welt!"); 
  } 
} 

Sehen Sie sich die Methode main() an, die in jeder Java-Application verwendet wird. Diese Methode wird als Klassenmethode definiert. Sie erkennen das am Schlüsselwort static. Warum ist das der Fall? Warum ist zwingend vorgeschrieben, dass main() statisch sein muss?

Wenn Sie die Java-VM starten und Ihre Application ablaufen lassen, sucht Java nach einer Methode main() und versucht, diese Methode für die Klasse aufzurufen. Das heißt, irgendwo im Java-System findet ein Aufruf ähnlich wie folgender statt.

MyApplication.main(); 

Java versucht, direkt für die Klasse MyApplication die Methode main() zu starten. Den Parameter in Klammern können wir an dieser Stelle ignorieren.

Damit tatsächlich für die Klasse MyApplication die Methode main() aufgerufen werden kann, muss sie statisch sein. Andernfalls könnte main() nur für Objekte aufgerufen werden. Das heißt, eine Methode main(), die nicht mit dem Schlüsselwort static definiert ist, könnte nur dann gestartet werden, wenn über ein Objekt der entsprechenden Klasse auf die Methode zugegriffen wird.

MyApplication application = new MyApplication(); 
application.main(); 

Würde das Java-System von der Klasse MyApplication mit new ein Objekt erstellen und dieses Objekt einer Referenzvariablen zuweisen, dann könnte über diese Referenzvariable und den Zugriffsoperator . auf jede beliebige Methode zugegriffen werden - egal, ob statisch oder nicht. In diesem Fall könnte also main() auch dann aufgerufen werden, wenn main() nicht statisch wäre.

Die Vorgehensweise des Java-System lässt sich jedoch nicht ändern. Java ruft für eine Application die Methode main() über die Klasse auf und erstellt nicht automatisch ein Objekt. Da main() nur dann über die Klasse aufgerufen werden kann, wenn es sich um eine Klassenmethode handelt, wird Ihre Application nicht starten können, falls Sie das Schlüsselwort static vergessen.

Merkwürdigerweise geht der Browser bei Applets genau andersrum vor. Sehen Sie sich den Code eines typischen Java-Applets an.

import java.applet.*; 
import java.awt.*; 

public class MyApplet extends Applet 
{ 
  String Text = "Hallo, Welt!"; 

  public void paint(Graphics g) 
  { 
    g.drawString(Text, 0, 10); 
  } 
} 

Die Methode paint() - ein typischer Event-Handler, der vom Browser dann für das Applet aufgerufen wird, wenn sich das Applet neu zeichnen soll - muss nicht als Klassenmethode definiert werden. Es ist kein static nötig - wie auch nicht bei den anderen vier bekannten Methoden für Applets init(), start(), stop() und destroy().

Lädt der Browser ein Applet, wird automatisch von der entsprechenden Klasse, die von java.applet.Applet abgeleitet ist, ein Objekt erstellt. Für dieses Objekt werden dann die bekannten Methoden automatisch aufgerufen, wann immer es nötig ist.

MyApplet applet = new MyApplet(); 
applet.init(); 
applet.start(); 
applet.paint(); 

Oben sehen Sie die typische Start-Sequenz für Applets, wie sie im Browser abläuft. Zuerst wird ein Objekt von der im HTML-Code der Webseite angegebenen Klasse erstellt. Dann werden für das Objekt die Methoden init(), start() und paint() automatisch aufgerufen.

Da der Browser standardmäßig ein Objekt erstellt, ist es nicht nötig, die bekannten Applet-Methoden als Klassenmethoden zu definieren. Sie können daher das Schlüsselwort static weglassen, was in der Praxis auch getan wird.

Das Schlüsselwort static wird immer dann verwendet, wenn die Funktionalität, die eine Methode bereitstellt, nicht für ein konkretes Objekt gilt, sondern unabhängig von Objekten bereit gestellt werden soll. Wenn eine Methode ihre Arbeit auch erledigen kann, ohne dass sie auf ein konkretes Objekt angewandt werden muss, dann bietet es sich an, diese Methode statisch zu machen. Andernfalls zwingen Sie sich oder andere Entwickler, die Ihre Klasse verwenden, erst ein Objekt zu erstellen, um dann über dieses Objekt die entsprechende Methode aufrufen zu können. Da das Erstellen von Objekten teuer ist und Ressourcen kostet - also Speicherplatz und Prozessorzeit - wäre ein direktes Aufrufen einer statischen Methode von Vorteil.


4.8 Aufgaben

Übung macht den Meister

Sie können die Lösungen zu allen Aufgaben in diesem Buch als ZIP-Datei erwerben.

  1. Erstellen Sie eine Java-Application, die eine Methode enthält, die zwei Kommazahlen vom Typ double erwartet. Beide Kommazahlen werden innerhalb der Methode multipliziert, das Ergebnis wird von der Methode zurückgegeben. Testen Sie Ihre Anwendung, indem Sie die Methode mit zwei Kommazahlen aufrufen und den Rückgabewert der Methode auf die Standardausgabe ausgeben. Für die Multiplikation zweier Zahlen müssen Sie den Operator * verwenden.

  2. Modifizieren Sie Ihre Lösung zur Aufgabe 1 dahingehend, dass die Methode, die die Zahlen vom Typ double multipliziert, nicht mehr statisch ist und die Anwendung immer noch wie angegeben funktioniert.

  3. Modifizieren Sie Ihre Lösung zur Aufgabe 1 dahingehend, dass Sie die Methode, die die Zahlen vom Typ double multipliziert, derart überladen, dass sie drei Parameter vom Typ double erwartet. Rufen Sie die neue Methode auf und geben Sie das Ergebnis der Multiplikation dreier beliebiger Kommazahlen auf die Standardausgabe aus.

  4. Modifizieren Sie Ihre Lösung zur Aufgabe 1 dahingehend, dass die Anwendung die beiden Kommazahlen vom Typ double in zwei Eigenschaften der Klasse speichert. Übergeben Sie die beiden Eigenschaften als Parameter an die Methode, die die Multiplikation vornimmt, und geben Sie das Ergebnis auf die Standardausgabe aus.

  5. Erstellen Sie eine Java-Application, die vier Methoden enthält, um zwei Ganzzahlen zu multiplizieren, zu dividieren, zu addieren und zu subtrahieren. Definieren Sie eine fünfte Methode, die das Vorzeichen einer Ganzzahl umdreht. Rufen Sie alle fünf Methoden mit beliebigen Zahlenwerten auf und geben Sie das Ergebnis auf die Standardausgabe aus.

  6. Modifizieren Sie Ihre Lösung zur Aufgabe 5 dahingehend, dass die Methoden nicht mehr mit beliebigen Zahlenwerten, sondern verschachtelt aufgerufen werden. Multiplizieren Sie die Zahlen 5 und 10, addieren Sie zum Ergebnis der Multiplikation den Wert 30 hinzu und subtrahieren Sie vom Ergebnis der Addition 45. Dividieren Sie anschließend 175 durch das Ergebnis der Subtraktion, ändern Sie das Vorzeichen des Ergebnisses der Division und geben Sie es dann auf die Standardausgabe aus. Führen Sie die gesamte Berechnung in einer einzigen Code-Zeile durch, indem Sie die für Aufgabe 5 erstellten Methoden verschachtelt aufrufen.

  7. Erstellen Sie ein Java-Applet, in dem Sie eine Methode definieren, die zwei Zeichenketten aneinanderhängt. Die Methode erwartet zwei Parameter vom Typ java.lang.String und gibt als Ergebnis ein Objekt vom Typ java.lang.String zurück. Die beiden übergebenen Parameter müssen in der Methode mit + verkettet werden. Definieren Sie zwei Eigenschaften vom Typ java.lang.String und setzen Sie sie auf "Hallo," und " Welt!". Rufen Sie die Methode zum Verketten von Zeichenketten auf, übergeben Sie die beiden Eigenschaften als Parameter und geben Sie den Rückgabewert der Methode in die Applet-Oberfläche aus.

  8. Modifizieren Sie Ihre Lösung zur Aufgabe 7 dahingehend, dass die Anwendung nicht mehr nur als Java-Applet verwendet werden kann, sondern auch als Java-Application. Erstellen Sie hierzu die für Java-Applications benötigte Methode main(), die ebenfalls die beiden Eigenschaften mit den Werten "Hallo," und " Welt!" verkettet und das Ergebnis auf die Standardausgabe ausgibt. Ihre Lösung soll also sowohl als Java-Applet in Webseiten eingebettet werden können als auch als Java-Application gestartet werden können.