Galileo Computing < openbook >
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.


Java ist auch eine Insel von Christian Ullenboom
Buch: Java ist auch eine Insel (Galileo Computing)
gp Kapitel 2 Sprachbeschreibung
gp 2.1 Anweisungen und Programme
gp 2.2 Elemente der Programmiersprache Java
gp 2.2.1 Textkodierung durch Unicode-Zeichen
gp 2.2.2 Unicode-Tabellen unter Windows
gp 2.2.3 Literale
gp 2.2.4 Bezeichner
gp 2.2.5 Reservierte Schlüsselwörter
gp 2.2.6 Token
gp 2.2.7 Semantik
gp 2.2.8 Kommentare
gp 2.2.9 Funktionsaufrufe als Anweisungen
gp 2.2.10 Die leere Anweisung
gp 2.2.11 Der Block
gp 2.3 Datentypen
gp 2.3.1 Primitive Datentypen
gp 2.3.2 Wahrheitswerte
gp 2.3.3 Variablendeklarationen
gp 2.3.4 Ganzzahlige Datentypen
gp 2.3.5 Die Fließkommazahlen
gp 2.3.6 Alphanumerische Zeichen
gp 2.3.7 Die Typanpassung (das Casting)
gp 2.3.8 Lokale Variablen, Blöcke und Sichtbarkeit
gp 2.3.9 Initialisierung von lokalen Variablen
gp 2.4 Ausdrücke, Operanden und Operatoren
gp 2.4.1 Zuweisungsoperator und Verbundoperator
gp 2.4.2 Präfix- oder Postfix-Inkrement und -Dekrement
gp 2.4.3 Unäres Minus und Plus
gp 2.4.4 Arithmetische Operatoren
gp 2.4.5 Die relationalen Operatoren
gp 2.4.6 Logische Operatoren
gp 2.4.7 Reihenfolge und Rang der Operatoren in der Auswertungsreihenfolge
gp 2.4.8 Überladenes Plus für Strings
gp 2.4.9 Was C(++)-Programmierer vermissen könnten
gp 2.5 Bedingte Anweisungen oder Fallunterscheidungen
gp 2.5.1 Die if-Anweisung
gp 2.5.2 Die Alternative wählen mit einer if/else-Anweisung
gp 2.5.3 Die switch-Anweisung bietet die Alternative
gp 2.6 Schleifen
gp 2.6.1 Die while-Schleife
gp 2.6.2 Schleifenbedingungen und Vergleiche mit ==
gp 2.6.3 Die do/while-Schleife
gp 2.6.4 Die for-Schleife
gp 2.6.5 Ausbruch planen mit break und Wiedereinstieg mit continue
gp 2.6.6 break und continue mit Sprungmarken
gp 2.7 Methoden einer Klasse
gp 2.7.1 Bestandteil einer Funktion
gp 2.7.2 Aufruf
gp 2.7.3 Methoden ohne Parameter
gp 2.7.4 Statische Methoden (Klassenmethoden)
gp 2.7.5 Parameter und Wertübergabe
gp 2.7.6 Methoden vorzeitig mit return beenden
gp 2.7.7 Nicht erreichbarer Quellcode bei Funktionen
gp 2.7.8 Rückgabewerte
gp 2.7.9 Methoden überladen
gp 2.7.10 Vorinitialisierte Parameter bei Funktionen
gp 2.7.11 Finale lokale Variablen
gp 2.7.12 Finale Referenzen in Objekten und das fehlende const
gp 2.7.13 Rekursive Funktionen
gp 2.7.14 Die Ackermann-Funktion
gp 2.7.15 Die Türme von Hanoi
gp 2.8 Weitere Operatoren
gp 2.8.1 Bitoperationen
gp 2.8.2 Vorzeichenlose Bytes in ein Integer und Char konvertieren
gp 2.8.3 Variablen mit Xor vertauschen
gp 2.8.4 Die Verschiebeoperatoren
gp 2.8.5 Setzen, Löschen, Umdrehen und Testen von Bits
gp 2.8.6 Der Bedingungsoperator
gp 2.9 Einfache Benutzereingaben


Galileo Computing

2.2 Elemente der Programmiersprache Javadowntop

Wir wollen nun über das Regelwerk, die Grammatik und Syntax der Programmiersprache Java sprechen. Wir wollen uns unter anderem über die Kodierung in Unicode, die Token und Bezeichner Gedanken machen.


Galileo Computing

2.2.1 Textkodierung durch Unicode-Zeichendowntop

Die Algorithmen für Java-Programme bestehen aus einer Folge von Anweisungen und Unterprogrammen. In Anweisungen und Funktionsnamen werden Folgen von Zeichen als Bezeichner eingesetzt, die diese Bezeichner und Funktionen kennzeichnen. Wir müssen ihnen Namen geben, und dabei dürfen wir uns der Zeichen auf der Tastatur bedienen. Der Zeichenvorrat nennt sich auch Lexikalik.

Texte werden in Java durch 16 Bit lange Unicode-Zeichen kodiert. Der Unicode-Zeichensatz beinhaltet die ASCII-Zeichen nach ISO8859-1 (Latin-1), daher gehören alle gewöhnlichen Zeichen von 0...255 auch zum erweiterten Zeichensatz. Da mit 16 Bit mehr als 65.000 Zeichen kodiert werden können, sind auch alle wichtigen Zeichensätze für andere Schriftsprachen kodiert. (Allerdings besteht die Diskussion, Unicode sollte auf 4 Bytes anwachsen, um noch mehr Zeichen aufzunehmen. Die Kodierung wird UTF-32 genannt.) Eine angenehme Konsequenz ist, dass auch der Quellcode in der Landessprache programmiert werden kann. Deutsche Umlaute stellen demnach für den Compiler kein Hindernis dar.


Tipp Obwohl Java intern Unicode für alle Bezeichner einsetzt, ist es dennoch ungünstig, Klassennamen zu wählen, die Unicode-Zeichen enthalten. Das Problem liegt nicht in der Programmiersprache begründet, sondern im Dateisystem der meisten Betriebssysteme. Sie speichern die Namen oft im alten 8-Bit-ASCII-Zeichensatz ab.

Schreibweise für Unicode-Zeichen

Kaum ein Editor dürfte in der Lage sein, alle Unicode-Zeichen anzuzeigen. Beliebige Unicode-Zeichen lassen sich als \uxxxx schreiben, wobei x eine hexadezimale Ziffer ist - also 0...1, A...F beziehungsweise a...f. Diese Sequenzen können an beliebiger Stelle eingesetzt werden. So können wir anstatt eines Anführungszeichens alternativ \u0027 schreiben, und dies wird vom Compiler als gleichwertig angesehen. Das Unicode-Zeichen \uffff ist nicht definiert und kann daher bei Zeichenketten als Ende-Symbol verwendet werden. Unicode-Zeichen für deutsche Sonderzeichen sind Folgende.


Zeichen Unicode
Ä,ä \u00c4, \u00e4
Ö, ö \u00d6, \u00f6
Ü,ü \u00dc, \u00fc
ß \u00df

Tabelle 2.1 Deutsche Sonderzeichen in Unicode

Anzeige der Unicode-Zeichen

Die Darstellung der Zeichen ist unter den meisten Plattformen noch ein großes Problem. Die Unterstützung für die Standardzeichen des ASCII-Alphabets ist dabei weniger ein Problem als die Sonderzeichen, die der Unicode-Standard definiert. Unter ihnen zum Beispiel der beliebte Smiley :-), der als Unicode \u263A (WHITE SMILING FACE) und \u2369 (WHITE FROWNING FACE) :-( definiert ist. Das Euro-Zeichen ist unter \u20ac zu finden.


Tipp Sofern die Sonderzeichen und Umlaute sich auf der Tastatur befinden, sollten keine Unicode-Kodierungen Verwendung finden. Der Autor von Quelltext sollte seine Leser nicht zwingen, eine Unicode-Tabelle zur Hand zu haben. Die Alternativdarstellung lohnt sich daher nur, wenn der Programmtext bewusst unleserlich gemacht werden soll.

Ein Versuch, den Smiley auf die Standardausgabe zu drucken, scheitert oft an der Fähigkeit des Terminals beziehungsweise der Shell. Hier ist eine spezielle Shell nötig, die aber bei den meisten Systemen erst noch in der Entwicklung ist. Und auch bei grafischen Oberflächen ist die Integration noch mangelhaft. Es wird Aufgabe der Betriebssystementwickler bleiben, dies zu ändern.1


Galileo Computing

2.2.2 Unicode-Tabellen unter Windowsdowntop

Unter Windows legt Microsoft das nützliche Programm CHARMAP.EXE für eine Zeichentabelle bei, mit der jede Schriftart auf ihre installierten Zeichen untersucht werden kann. Praktischerweise zeigt die Zeichentabelle auch gleich die Position in der Unicode-Tabelle an.

Unter der erweiterten Ansicht lassen sich zusätzlich auch noch Unicode-Unterbereiche auswählen, wie etwa Währungszeichen oder unterschiedliche Sprachen. Im Unterbereich Latin finden sich zum Beispiel die Zeichen aus der französischen (etwa C mit Cedille unter 00c7) und spanischen (n mit Tilde unter 00F1) Schrift und bei Allgemeinen Interpunktionszeichen findet sich das umgedrehte (invertierte) Fragezeichen bei 00BF.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 2.1 Zeichentabelle unter Windows XP


Galileo Computing

2.2.3 Literaledowntop

Ein Literal ist ein konstanter Ausdruck. Es gibt Literale von verschiedenen Typen:

gp Die Wahrheitswerte true und false
gp Integrale Literale für Zahlen, etwa 12 oder -32
gp Zeichenliterale, etwa 'X' oder '\n'
gp Gleitkommaliterale: 12.567 oder -9.999E-2
gp Stringliterale für Zeichenketten wie "Paolo Pinkas"

Galileo Computing

2.2.4 Bezeichnerdowntop

Für Variablen (und damit Konstanten), Methoden, Klassen und Schnittstellen werden Bezeichner - auch Identifizierer (von eng. identifier) genannt - vergeben, die die entsprechenden Bausteine anschließend im Programm identifizieren. Unter Variablen sind dann Daten verfügbar, Methoden sind die Prozeduren in objektorientierten Programmiersprachen und Klassen sind die Bausteine objektorientierter Programme.


Beispiel Im folgenden kleinen Java-Programm sind die Bezeichner unterstrichen:
class Main
{
  public static void main( String args[] )
  {
    System.out.println( "Hallo Welt" );
  }
}

Ein Bezeichner ist eine Folge von Zeichen, die fast beliebig lang sein kann (die Länge ist nur theoretisch festgelegt). Die Zeichen sind Elemente aus dem gesamten Unicode-Zeichensatz, und jedes Zeichen ist für die Identifikation wichtig. Das heißt, ein Bezeichner, der 100 Zeichen lang ist, muss auch immer mit allen 100 Zeichen korrekt angegeben werden. Manche C- und FORTRAN-Compiler sind in dieser Hinsicht etwas großzügiger und bewerten nur die ersten Stellen.

Jeder Java-Bezeichner muss entweder mit einem Unicode-Buchstaben oder mit »_« oder »$« beginnen.2 Ein Unicode-Buchstabe ist zum Beispiel aus dem Bereich »A« bis »Z« (auch »a« bis »z«), aber nicht zwingend beschränkt auf lateinische Zeichen. Auch griechische Buchstaben sind Unicode-Buchstaben. Nach dem ersten Buchstaben können neben den Buchstaben auch Ziffern folgen. Dass der Unterstrich mittlerweile mit zu den Buchstaben zählt, ist nicht weiter verwunderlich, doch dass das Dollarzeichen mitgezählt wird, ist schon erstaunlich. Sun erklärt den Einsatz einfach damit, dass diese beiden Zeichen »aus historischen Gründen« mit aufgenommen wurden. Eine sinnvollere Erklärung ist, dies mit der Verwendung von maschinengeneriertem Code zu erklären. Es bleibt noch einmal zu erwähnen, dass zwischen Groß-/Kleinschreibung unterschieden wird. Dennoch sollte ein eigener Bezeichner nicht mit $ beginnen.

Die folgende Tabelle listet einige gültige und ungültige Bezeichner auf.


Gültige Bezeichner Ungültige Bezeichner
mami 2und2macht4
kulliReimtSichAufUlli class
IchWeißIchMussAndréAnrufen hose gewaschen
RAPHAEL_IST_LIEB hurtig!

Tabelle 2.2 Beispiele für Bezeichner in Java

mami ist genau ein Bezeichner, der nur aus Alphazeichen besteht und daher korrekt ist. Auch kulliReimtSichAufUlli ist korrekt. Der Bezeichner zeigt zusätzlich die in Java übliche Bezeichnerbildung; denn besteht dieser aus mehreren einzelnen Wörtern, werden diese einfach ohne Leerzeichen hintereinander gesetzt, jedes Teilwort (außer dem Ersten) beginnt jedoch dann mit einem Großbuchstaben. Leerzeichen sind in Bezeichnern nicht erlaubt, und daher ist auch hose gewaschen ungültig. Auch das Ausrufezeichen ist, wie viele Sonderzeichen, ungültig. IchWeißIchMussAndréAnrufen ist jedoch wieder korrekt, auch wenn es ein Apostroph-é enthält. Treiben wir es weiter auf die Spitze, dann sehen wir einen gültigen Bezeichner, der nur aus griechischen Zeichen gebildet ist. Auch der erste Buchstabe ist ein Zeichen, anders als in 2und2macht4. Und class ist ebenso ungültig, da der Name schon von Java belegt ist.


Hinweis In Java-Programmen bilden sich Bezeichnernamen oft aus zusammengesetzen Wörtern einer Beschreibung. Das bedeutet, dass in einem Satz wie »schönes Wetter heute« die Leerzeichen entfernt werden und die nach dem ersten Wort folgenden Wörter mit Großbuchstaben beginnen. Damit wird aus dem Beispielsatz anschließend »schönesWetterHeute«. Sprachwissenschaftler nennen diese gemischte Groß- und Kleinschreibung Binnenmajuskel.

Die Tabelle im nächsten Abschnitt zeigt uns, welche Namen wir nicht verwenden können. Für class nehmen Programmierer als Ersatz gerne clazz.


Galileo Computing

2.2.5 Reservierte Schlüsselwörterdowntop

Bestimmte Wörter sind als Bezeichner nicht zulässig, da sie als Schlüsselwörter durch den Compiler besonders behandelt werden. Schlüsselwörter bestimmen die »Sprache« eines Compilers. Nachfolgende Zeichenfolgen sind Schlüsselwörter (beziehungsweise Literale im Fall von true, false und null)3 und in Java daher nicht als Bezeichnernamen möglich:


abstract assert boolean break byte
byvalue† case cast† catch char
class const† continue default do
double else enum extends final
finally float for future† generic†
goto† if implements import instanceof
int inner† interface long native
new null operator† outer† package
private protected public rest† return
short static strictfp super switch
synchronized this throw throws transient
try var† void volatile while

Tabelle 2.3 Reservierte Wörter in Java

Obwohl die mit † gekennzeichneten Wörter zurzeit nicht von Java benutzt werden, können doch keine Variablen dieses Namens definiert werden.


Galileo Computing

2.2.6 Tokendowntop

Ein Token ist eine lexikalische Einheit, die dem Compiler die Bausteine des Programms liefert. Der Compiler erkennt an der Grammatik einer Sprache, welche Folgen von Zeichen ein Token bilden. Für Bezeichner heißt dies beispielsweise: Nimm die nächsten Zeichen, solange auf einen Buchstaben nur Buchstaben oder Ziffern folgen. Eine Zahl wie 1982 bildet zum Beispiel ein Token durch folgende Regel: Lese solange Ziffern, bis keine Ziffer mehr folgt. Bei Kommentaren bilden die Kombinationen /* und */ ein Token.

Whitespace

Problematisch wird es in einer Sprache immer dann, wenn der Compiler die Token nicht voneinander unterscheiden kann. Daher fügen wir Trennzeichen (engl. whitespace), auch Wortzwischenräume genannt, ein. Zu den Trennern zählen Leerzeichen, Tabulatoren, Zeilenvorschub- und Seitenvorschubzeichen. Außer als Trennzeichen haben diese Zeichen keine Bedeutung. Daher können sie in beliebiger Anzahl zwischen die Token gesetzt werden. Das heißt auch, beliebig viele Leerzeichen sind zwischen Token gültig. Und da wir damit nicht geizen müssen, können sie einen Programmabschnitt enorm verdeutlichen. Programme sind besser lesbar, wenn sie luftig formatiert sind.

Folgendes dient nicht der optimalen Lesbarkeit, obwohl es vom Compiler akzeptiert wird:

class _{static long _
(long __,long  ___) {
return __==0 ?___+ 1:
___==0?_(__-1,1):_(__
-1,_(__, ___-1)) ;  }
static  {int _=2 ,___
= 2;System.out.print(
"a("+_+','+___+ ")="+
_ (_,  ___) ) ;System
.exit(1);}}//(C) Ulli

Neben den Trennern gibt es noch 9 Zeichen, die als Separator definiert werden:

; , . ( ) { } [ ]

Galileo Computing

2.2.7 Semantikdowntop

Die Syntax eines Java-Programms definiert die Token und bildet so das Vokabular. Richtig geschriebene Programme müssen aber dennoch nicht korrekt sein. Unter dem Begriff »Semantik« fassen wir daher die Bedeutung eines syntaktisch korrekten Programms zusammen. Die Semantik bestimmt, was das Programm macht. Die Abstraktionsreihenfolge ist also Lexikalik, Syntax und Semantik. Der Compiler durchläuft diese Schritte, bevor er den Bytecode erzeugen kann.

Programme

Programme setzen sich aus Anweisungen zusammen. In Java können jedoch nicht einfach Anweisungen in eine Datei geschrieben und dem Compiler übergeben werden. Sie müssen zunächst in einen Rahmen gepackt werden. Dieser Rahmen definiert die Hauptklasse mit ihren Funktionen.

Auch wenn die folgenden Programmcodezeilen am Anfang etwas befremdend wirken, wir werden sie zu einem späteren Zeitpunkt noch genauer erklären. Wir geben der folgenden Datei den Namen Main.java:

Listing 2.1 Main.java

class Main
{
  public static void main( String args[] )
  {
  // Hier ist der Anfang unserer Programme
  // Jetzt ist hier Platz für unsere eigenen Anweisungen
  // Hier enden unsere Programme
  }
}

Eclipse zeigt Schlüsselwörter, Literale und Kommentare farbig an. Diese Farbgebung lässt sich im Konfigurationsmenü ändern.

Ein Java-Programm muss immer in einer Klasse definiert sein. Wir haben sie Main genannt, der Name ist jedoch beliebig. In geschweiften Klammern folgen benutzerdefinierte Methoden, also Funktionen, die die Klasse anbietet. Eine Funktion ist eine Sammlung von Anweisungen unter einem Namen. Mathematische Funktionen sind mit Funktionen aus Programmiersprachen vergleichbar. Eine Sinus-Funktion schafft es beispielsweise, zu einem gegebenen Wert den Sinus zu berechnen. Wir wissen zwar nicht, wie die Funktion das macht, aber sie kann es. Der Begriff »Funktion« und der objektorientierte Name »Methode« sind in diesem Tutorial synonym verwendet. Vor einer Methode stehen unterschiedliche Modifizierer. Der Modifizierer static sagt, dass die Methode auch ohne Objekt benutzt werden kann. Wir werden in den folgenden Kapiteln nur mit statischen Methoden arbeiten.

Wir programmieren hier eine besondere Funktion, die sich main() nennt. Die Schlüsselwörter davor und die Angabe in dem Paar runder Klammern hinter dem Namen müssen wir einhalten. Die Funktion main() ist für die Laufzeitumgebung etwas ganz Besonderes, denn beim Aufruf des Java-Interpreters mit einem Klassennamen wird unsere Funktion als Erstes ausgeführt.4 Demnach werden genau die Anweisungen ausgeführt, die innerhalb der geschweiften Klammern stehen. Halten wir uns fälschlicherweise nicht an die Syntax für den Startpunkt, so kann der Interpreter die Ausführung nicht beginnen und wir haben einen semantischen Fehler gemacht, obwohl die Funktion selbst korrekt gebildet ist. Innerhalb von main() befindet sich der Name args, mit dem die Parameter angesprochen werden. Der Name ist willkürlich, wir werden allerdings immer args verwenden.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Eclipse gibt im Falle eines Fehlers sehr viele Hinweise. Im folgenden Beispiel fehlt die schließende Klammer. Ein Fehler im Quellode wird von Eclipse mit einer roten unterkringelten Linie angezeigt. Als weiterer Indikator wird (unter Umständen erst beim Speichern) ein kleines rundes Kreuz an der Fehlerzeile angezeigt. Gleichzeitig findet sich im Schieberegler ein roter kleiner Block. Im Packager Explorer findet sich ebenfalls ein Hinweis auf Fehler.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Hinter den beiden Geteilt-Zeichen // befindet sich ein Kommentar. Er gilt bis zum Ende der Zeile und dient dazu, Erläuterungen zu den Quellcodezeilen hinzuzufügen, die ihn verständlicher machen.

Programme übersetzen und starten

Der Quellcode eines Java-Programms ist so allein nicht ausführbar. Ein spezielles Programm, der Compiler (auch Übersetzer genannt), transformiert das geschriebene Programm in eine andere Repräsentation. Ein Quellcode mit Anweisungen für Programme muss aber nicht zwingend übersetzt werden. Eine andere Gattung für ein Ablaufmodell ist der Interpreter. Er liest die Datei Schritt für Schritt ein und führt dann die Anweisungen aus. Der Compiler liest die Datei in einem Rutsch und meldet Fehler. Häufig werden Skriptsprachen interpretiert, früher waren es oft BASIC-Programme. Compiler für geläufige Programmiersprachen wie C(++) oder Delphi übersetzen den Quellcode in Maschinencode. Das ist Binärcode, der vom Prozessor im Computer direkt ausführbar ist. Da unterschiedliche Rechner aber unterschiedliche Prozessoren besitzen, sind die Programme nicht direkt auf verschiedenen Rechnerplattformen ausführbar. Java ist jedoch als Programmiersprache entworfen worden, die plattformunabhängig ist, sich also nicht an einen physikalischen Prozessor klammert. Der Compiler übersetzt den Quellcode nicht in Binärcode für einen konkreten Prozessor, sondern in einen plattformunabhängigen Code, den Bytecode. Prozessoren wie Intel-, AMD- oder G5-CPU können aber mit diesem Bytecode nichts anfangen. Hier hilft ein Interpreter weiter. Dieser liest Anweisung für Anweisung aus dem Bytecode und führt entsprechende Befehle auf dem Mikroprozessor aus. Daher ist Java eine compilierte und interpretierte Sprache zugleich.


Galileo Computing

2.2.8 Kommentaredowntop

Programmieren heißt nicht nur, einen korrekten Algorithmus in einer Sprache auszudrücken, sondern auch, unsere Gedanken verständlich zu formulieren. Dies geschieht beispielsweise durch eine sinnvolle Namensgebung für Programmobjekte wie Klassen, Funktionen und Variablen. Ein selbsterklärender Klassenname hilft den Entwicklern erheblich. Doch die Lösungsidee und der Algorithmus werden auch durch die schönsten Variablennamen nicht zwingend klarer. Damit Außenstehende (und wir nach Monaten selbst) unsere Lösungsidee schnell nachvollziehen und später das Programm erweitern oder abändern können, werden Kommentare in den Quelltext eingeführt. Sie dienen nur den Lesern der Programme, haben aber auf die Abarbeitung keine Auswirkungen.

Kommentarblöcke können durch /* und */ abgetrennt werden. Zwischen diesen Zeichen kann nahezu jeder beliebige Text stehen. Da es keinen Präprozessor gibt, ist es Aufgabe des Compilers, die Bemerkungen aus dem Quelltext zu entfernen. Da im Einzelfall nur Zeilen auskommentiert werden sollen, ist in Java auch das in C++5 verwendete // erlaubt, welches wir schon kennen gelernt haben.

// Zeilenkommentar

/*
 * Blockkommentar
 */

Abbildung
Hier klicken, um das Bild zu Vergrößern

Die Tastenkombination (Strg)+(/) kommentiert eine Zeile oder einen Block aus. Eclipse setzt vor die Zeile beziehungsweise Zeilen die Zeichen //. (Strg)+(\) nimmt die Kommentare einer Zeile oder Blöcke wieder zurück.

Dokumentationskommentare

Neben dem Blockkommentar bietet Java eine interessante Möglichkeit der Programmdokumentation. Die Zeichen /** und */ beschreiben einen so genannten Dokumentationskommentar (engl. Doc-Comment), welcher vor Methoden- oder Klassendefinitionen angewendet wird.


Beispiel Dokumentationskommentar
/**
 * Hier drinnen ist ein Doc-Kommentar.
 */

Der Teil zwischen den Kommentaren wird mit einem externen Dienstprogramm in HTML- oder Framemaker-Dokumente umgewandelt.

Blockkommentare dürfen nicht geschachtelt sein. Ein Zeilenkommentar darf aber im Blockkommentar enthalten sein.


Galileo Computing

2.2.9 Funktionsaufrufe als Anweisungendowntop

Bisher kennen wir keine konkreten Anweisungen. Daher möchte ich jetzt eine einfache Anweisung vorstellen, die wichtig für Programme ist: der Funktionsaufruf. Allgemein hat er folgendes Format:

funktionsname();

Innerhalb der Klammern dürfen wir Parameter angeben. Es lassen sich auch Funktionen in dieser Form anwenden, die ein Ausdruck sind und ein Ergebnis zurückgeben, beispielsweise eine Sinus-Funktion. Der Rückgabewert wird dann verworfen. Im Fall der Sinus-Funktion macht das wenig Sinn, denn sie macht außer der Berechnung nichts anderes.

Wir interessieren uns für eine Funktion, die eine Zeichenkette auf dem Bildschirm ausgibt. Sie heißt println(). Die meisten Methoden verraten durch ihren Namen, was sie leisten, und für eigene Programme ist es sinnvoll, aussagekräftige Namen zu verwenden. Wenn die Java-Entwickler die Methode glubschi()6 genannt hätten, würde uns der Sinn der Methode verborgen bleiben. println() zeigt jedoch durch den Wortstamm »print« an, dass etwas geschrieben wird. Die Endung ln (kurz für line) bedeutet, dass noch ein Zeilenvorschubzeichen ausgegeben wird. Umgangssprachlich heißt das: Eine neue Ausgabe beginnt in der nächsten Zeile. Neben println() existiert die Bibliotheksfunktion print(), die keinen Zeilenvorschub hervorruft.

Die printXXX()7-Methoden können in Klammern unterschiedliche Parameter bekommen. Ein Parameter ist ein Wert, den wir der Funktion beim Aufruf mitgeben wollen. Wir wollen die Diskussion über Parameter aber noch etwas verschieben. Unser printXXX()-Aufruf soll lediglich Zeichenketten ausgeben. (Ein anderes Wort für Zeichenketten ist String.) Ein String ist eine Folge von Buchstaben, Ziffern oder Sonderzeichen in doppelten Anführungszeichen:

"Ich bin ein String"
"Ich auch. Und ich koste 7.59 _i_"

Um die obere Ausgabe mit dem Funktionsaufruf und einem trennenden Zeilenvorschub auf den Bildschirm zu bekommen, schreiben wir:

System.out.println( "Ich bin ein String" );
System.out.println();                // Gibt eine Leerzeile aus
System.out.println( "Ich auch. Und ich koste 7.59 _i_" );

Auch wenn eine Funktion keine Parameter erwartet, muss beim Aufruf hinter dem Funktionsnamen ein Klammerpaar folgen. Dies ist konsequent, da wir so wissen, dass es ein Funktionsaufruf ist und nichts anderes. Andernfalls führt es zu Verwechslungen mit Variablen.

Eine weitere Eigenschaft von Java wird ebenfalls an dem Funktionsaufruf sichtbar. Es gibt Methoden, die unterschiedliche Parameter (eine andere Anzahl oder einen unterschiedlichen Typ) besitzen, aber gleichen Namen tragen. Diese Funktionen nennen wir überladen. Die printXXX()-Methoden sind sogar vielfach überladen und akzeptieren neben Strings auch weitere Werte als Parameter.

Programmieren wir eine ganze Java-Klasse, die etwas auf dem Bildschirm ausgibt.

Listing 2.2 Main.java

class Main
{
  public static void main( String args[] )
  {
  // Hier ist der Anfang unserer Programme
    System.out.println( "Hallo Javanesen" );
  // Hier enden unsere Programme
  }
}

Hinweis Anweisungen wie ein Funktionsaufruf enden immer mit einem Semikolon.

Erste Idee der Objektorientierung

In einer objektorientierten Programmiersprache sind alle Methoden an bestimmte Objekte gebunden (daher der Begriff objektorientiert). Betrachten wir zum Beispiel das Objekt Radio. Ein Radio spielt Musik ab, wenn der Einschalter betätigt wird und ein Sender und die Lautstärke eingestellt sind. Ein Radio bietet also bestimmte Dienste (Operationen) an, wie Musik an/aus, lauter/leiser. Zusätzlich hat ein Objekt auch noch einen Zustand. Es ist zum Beispiel die Farbe oder das Baujahr. Wichtig in objektorientierten Sprachen ist, dass die Operationen und Zustände immer (und da gibt es keine Ausnahmen) an Objekte beziehungsweise Klassen gebunden sind (mehr zu dieser Unterscheidung später). Der Aufruf einer Methode auf ein Objekt richtet die Anfrage genau an ein bestimmtes Objekt. Steht in einem Java-Programm einfach nur die Anweisung lauter, so weiß der Compiler nicht, wen er fragen soll. Was ist, wenn es auch noch einen Fernseher gibt? Aus diesem Grunde verbinden wir das Objekt, das etwas kann, mit der Operation. Ein Punkt trennt das Objekt von der Operation oder dem Zustand.

So gehört auch println() zu einem Objekt, welches die Bildschirmausgabe übernimmt. Dass eine Methode immer zu einem Objekt gehört, können wir auch an unserem eigenen Programm überprüfen. main() gehört zu der Klasse Main, die später ein Objekt bilden kann. Daher können wir in Java auch nicht einfach die Ausgabeanweisung schreiben. println() gehört zu einem Objekt mit dem Namen out. Dieses Objekt ist wiederum Teil der Klasse System. Wir können das vergleichen mit einem Aufruf zum Beispiel von

BRD.aktuellerBundeskanzler.fragen( "Wieso kassieren ARD" +
 " und ZDF jährlich 11 Mrd. Mark Rundfunkgebühren"+
 " und müssen davon nichts abführen?" );

Mehr zu diesen Aufrufen zu einem späterem Zeitpunkt. Das obige Beispiel macht aber jetzt schon deutlich, dass Strings mit dem Plus zusammengehängt werden können.


Galileo Computing

2.2.10 Die leere Anweisungdowntop

Die einfachste Anweisung besteht nur aus einem Semikolon und ist die leere Anweisung:

;

Sie wird verwendet, wenn die Sprachgrammatik eine Anweisung vorschreibt, aber in dem Programmablauf keine Anweisung vorkommen muss. So muss etwa hinter dem Schleifenkopf eine Anweisung folgen. Wir werden bei den Schleifen eine Anwendung der leeren Anweisung sehen.


Galileo Computing

2.2.11 Der Blocktoptop

Ein Block innerhalb von Methoden oder statistischen Blöcken fasst eine Gruppe von Anweisungen zusammen, die hintereinander ausgeführt werden. Dazu werden die Anweisungen zwischen geschweiften Klammern geschrieben:

{
  Anweisung1;
  Anweisung2;
  ...
}

Ein Block kann überall dort verwendet werden, wo auch eine einzelne Anweisung stehen kann. Der neue Block hat jedoch eine Besonderheit für Variablen, denn er bildet einen lokalen Bereich für die darin befindlichen Anweisungen inklusive der Variablen.

Leerer Block und geschachtelte Blöcke

Ein Block ohne Anweisung nennt sich leerer Block: {}. Er verhält sich wie eine leere Anweisung, also wie ein Semikolon. Blöcke können auch geschachtelt werden, sodass Folgendes in der Funktion main() in Ordnung ist:

public static void main( String args[] )
{
  { System.out.println( "Hallo Computer" ); {{}}{{}{}}}
}





1 Mit veränderten Dateiströmen lässt sich dies etwas in den Griff bekommen. So lässt sich beispielsweise mit einem speziellen OutputStream-Objekt eine Konvertierung für die Windows-NT-Shell vornehmen, so dass auch dort die Sonderzeichen erscheinen.

2 Ob ein Zeichen ein Buchstabe ist, lässt sich mit der Funktion Character.isLetter() erfragen; ob er ein gültiger Bezeichner-Buchstabe ist, liefern die Funktionen isJavaIdentifierStart() für den Startbuchstaben und isJavaIdentifierPart() für den Rest.

3 Siehe dazu Abschnitt 3.9 (Keywords) der Sprachdefinition unter>http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.htmlges.

4 Na ja, so ganz präzise ist das auch nicht. In einem static-Block könnten wir auch einen Funktionsaufruf setzen, doch das wollen wir hier einmal nicht annehmen. static-Blöcke werden beim Laden der Klassen in die virtuelle Maschine ausgeführt. Andere Initialisierungen sind dann auch schon gemacht.

5 In C++ haben die Entwickler übrigens das Zeilenkommentarzeichen // aus der Vor-Vorgängersprache BCPL wieder eingeführt, was in C entfernt wurde.

6 Bei uns am Niederrhein steht glubschi für etwas Glitschiges, Schleimiges.

7 Abkürzung für Methoden, die mit print beginnen, also print() und println().





Copyright (c) Galileo Press GmbH 2004
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de