Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 5 (Tiger-Release)
Buch: Java ist auch eine Insel
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
    gp 2.4.2 Verbundoperatoren
    gp 2.4.3 Präfix- oder Postfix-Inkrement und -Dekrement
    gp 2.4.4 Unäres Minus und Plus
    gp 2.4.5 Arithmetische Operatoren
    gp 2.4.6 Die relationalen Operatoren
    gp 2.4.7 Logische Operatoren
    gp 2.4.8 Reihenfolge und Rang der Operatoren in der Auswertungsreihenfolge
    gp 2.4.9 Überladenes Plus für Strings
    gp 2.4.10 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 Funktionen (Klassenmethoden)
    gp 2.7.5 Parameter, Argument 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 Vorgegebener Wert für nicht aufgeführte Argumente
    gp 2.7.11 Finale lokale Variablen
    gp 2.7.12 Rekursive Funktionen
    gp 2.7.13 Die Ackermann-Funktion
    gp 2.7.14 Die Türme von Hanoi
  gp 2.8 Dokumentationskommentare
    gp 2.8.1 Ein Dokumentationskommentar setzen
    gp 2.8.2 Mit javadoc eine Dokumentation erstellen
    gp 2.8.3 Generierte Dateien
    gp 2.8.4 Weitere Dokumentationskommentare
    gp 2.8.5 Schalter für das Programm javadoc
    gp 2.8.6 JavaDoc und Doclets
    gp 2.8.7 Bitoperationen
    gp 2.8.8 Vorzeichenlose Bytes in ein Integer und Char konvertieren
    gp 2.8.9 Variablen mit Xor vertauschen
    gp 2.8.10 Die Verschiebeoperatoren
    gp 2.8.11 Setzen, Löschen, Umdrehen und Testen von Bits
    gp 2.8.12 Der Bedingungsoperator
  gp 2.9 Einfache Benutzereingaben


Galileo Computing

2.2 Elemente der Programmiersprache Javdowntop

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.

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. Bei dem Namen eines Bezeichners dürfen wir uns der Zeichen auf der Tastatur bedienen und noch viel mehr. In Java lässt sich ein Bezeichner aus einer großen Anzahl Zeichen zusammensetzen; der Zeichenvorrat nennt sich Lexikalik.


Galileo Computing

2.2.1 Textkodierung durch Unicode-Zeichen  downtop

Texte werden in Java durch 16 Bit lange Unicode-Zeichen kodiert. Jedem Zeichen ist ein eindeutiger Zahlenwert (engl. code point) zugewiesen, so dass zum Beispiel das große A an Position 65 liegt. 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. Seit Version 5.0 unterstützt Java Surrogate, die den Bereich der »Basic Multilingual Plane (BMP)« vergrößern. Ein Surrogate-Paar besteht aus zwei 16-Bit Zeichen, die dann ein neues Zeichen definieren.

Grundsätzlich könnte Java-Quellcode in der Landessprache programmiert werden. Deutsche Umlaute stellen für den Compiler kein Hindernis dar, genauso wie griechische Symbole. Allerdings ist es fragwürdig, ob ein solches Unicode-Programm sinnvoll ist, denn Editoren haben mit 16-Bit Unicode-Zeichen ihre Schwierigkeiten, genauso wie Dateisysteme. Obwohl Java intern Unicode für alle Bezeichner einsetzt, ist es ungünstig, Klassennamen zu wählen, die Unicode-Zeichen enthalten, denn das Dateisystem der meisten Betriebssysteme speichert die Namen oft im alten 8-Bit-ASCII-Zeichensatz ab, so dass Teile vom 16-Bit Unicode-Zeichen verloren gehen.

Schreibweise für Unicode-Zeichen/Unicode escapes

Kaum ein Editor dürfte in der Lage sein, alle Unicode-Zeichen anzuzeigen. Beliebige Unicode-Zeichen lassen sich für den Compiler über Unicode escapes mit \uxxxx schreiben, wobei x eine hexadezimale Ziffer ist – also 0...1, A...F beziehungsweise a...f. Diese sechs ASCII-Zeichen, die das Unicode beschreiben, lassen sich in jedem ASCII-Texteditor schreiben, so dass kein Unicode-fähiger Editor nötig ist.

Die Unicode-Escape-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.


Tabelle 2.1   Deutsche Sonderzeichen in Unicode

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

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.


Galileo Computing

2.2.2 Unicode-Tabellen unter Windows  downtop

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 Literale  downtop

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 Bezeichner  downtop

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


Tabelle 2.2   Beispiele für Bezeichner in Java

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

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örter  downtop

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) und in Java daher nicht als Bezeichnernamen möglich:


Tabelle 2.3   Reservierte Wörter in Java

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

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 Token  downtop

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 Semantik  downtop

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 Funktionen 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. 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 ein Parameter mit dem Namen args. Der Name ist willkürlich gewählt, 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 Kommentare  downtop

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.

In Java gibt es drei Möglichkeiten für Kommentare:

gp  Zeilenkommentare mit //
gp  Blockkommentare mit /* */
gp  Besondere Blockkommentare, die JavaDoc-Kommentare mit /** */

In einem Blockkommentar kann nahezu jeder beliebige Text stehen, nur kein */, denn Blockkommentare dürfen nicht geschachtelt sein.


/*
 * Blockkommentar
 */

Um den Rest einer Zeile und auch eine ganze Zeile auszukommentieren werden zwei Schrägstriche // verwendet. Der Kommentar gilt von den Zeichen an bis zum Ende der Zeile, also dem Zeichenumbruchszeichen. Ein Zeilenkommentar darf im Blockkommentar enthalten sein und Zeilenkommentare können Zeilenkommentare enthalten.


// Zeilenkommentar
System.out.println( "Hallo" );          //  Das grüßt dich.
// System.out.println( "Hallo" );       //  Das grüßt dich (nicht).eclipse

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

Die Tastenkombination (Strg)+(/) kommentiert eine Zeile – oder mehrere Zeilen im Fall einer Selektion – aus. Eclipse setzt dann vor jede Zeile die Kommentarzeichen //. In einer kommentieren Zeile nimmt erneutes (Strg)+(/) die Kommentare einer Zeile wieder zurück.

Kommentare mit Stil

Alle Kommentare und Bemerkungen sollten in Englisch verfasst werden, um Projektmitgliedern aus anderen Ländern das Lesen zu vereinfachen. Für allgemeine Kommentare sollten wir die Zeichen // benutzen. Sie haben zwei Vorteile:

gp  Bei Editoren, die Kommentare nicht farblich hervorheben – oder bei einer einfachen Quellcodeausgabe auf der Kommandozeile – lässt sich ersehen, dass eine Zeile, die mit // beginnt, ein Kommentar ist. Einen Quelltext zu übersehen, der für mehrere Seiten mit den Kommentarzeichen /* und */ unterbrochen wird, ist schwierig. Zeilenkommentare machen deutlich, wo Kommentare beginnen und wo sie enden.
gp  Der Einsatz der Zeilenkommentare eignet sich besser dazu, während der Entwicklungs- und Debug-Phase Codeblöcke auszukommentieren. Benutzen wir zur Programmdokumentation die Blockkommentare, so sind wir eingeschränkt, denn Kommentare dieser Form können wir nicht schachteln. Zeilenkommentare können einfacher geschachtelt werden.

Galileo Computing

2.2.9 Funktionsaufrufe als Anweisungedowntop

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 auch Argumente angeben, wenn die Funktion das erlaubt. Es lassen sich auch Funktionen in dieser Form anwenden, die ein Ausdruck sind und ein Ergebnis zurückgeben, beispielsweise eine Sinus-Funktion. Wird mit dem Ergebnis nichts gemacht, wird der Rückgabewert verworfen. Im Fall der Sinus-Funktion ist das nicht sinnvoll, denn sie macht außer der Berechnung nichts anderes.

Die Funktion print() und println()

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() 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()Methoden können in Klammern unterschiedliche Argumente bekommen. Ein Argument ist ein Wert, den wir der Funktion beim Aufruf mitgeben wollen. Wir wollen die Diskussion über Argumente 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"

Bildschirmausgaben

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 Argumente 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 Argumente (eine andere Anzahl oder einen unterschiedlichen Typ) besitzen, aber einen gleichen Namen tragen. Diese Funktionen nennen wir überladen. Die printXXX()-Methoden sind sogar vielfach überladen und akzeptieren neben Strings auch weitere Werte als Argumente.

Implementieren10  wir eine vollständige 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. Das Semikolon dient auch nicht wie in PASCAL zur Trennung von Anweisungen, sondern es schließt sie ab. So hat das Semikolon etwa die Bedeutung eines Punktes in natürlichen Sprachen – ein Punkt schließt einen Satz ab.

System.out und System.err

Das Laufzeitsystem bietet uns zwei Ausgabekanäle, in die wir normale Ausgaben und Fehler leiten können. Der Vorteil ist, dass über diese Unterteilung die Fehler von der herkömmlichen Ausgabe getrennt werden können. Standardausgaben wandern in System.out und Fehlerausgaben werden in System.err weitergeleitet. out und err sind vom gleichen Typ, so dass die println()- oder print()-Varianten bei beiden gleich bleiben.


System.out.println( "Das ist eine normale Ausgabe" );
System.err.println( "Das ist eine Fehlerausgabe" );

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

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

Eclipse stellt normale Ausgaben blau dar und Fehlerausgaben rot. Damit ist leicht zu erkennen, welche Ausgabe in welchen Kanal geschickt wurde.

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 Anweisung  downtop

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 Block  toptop

Ein Block innerhalb von Methoden oder statistischen Blöcken fasst eine Gruppe von Anweisungen zusammen, die hintereinander ausgeführt werden. Anders gesagt: Ein Block ist eine Anweisung, der in den geschweiften Klammern { } eine Folge von Anweisungen zu einer neuen Anweisung zusammenfasst.


{
  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  Ein Unicode-Editor unter Windows ist SC UniPad unter http://www.unipad.org/main/.

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

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

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

5  Das ist in C(++) unglücklich, denn so wird ein Ausdruck *s/*t nicht wie erwartet geparst. Erst das Leerzeichen »hilft« dem Parser das gewünschte zu erkennen: Teile

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

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

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

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

10  Implementieren stammt vom lateinischen Wort »implere« ab, was für erfüllen und ergänzen steht.





Copyright © 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