2.3 Elemente einer Programmiersprache   Wir haben einige Beispiele für Java-Programme gesehen und wollen nun über das Regelwerk, die Grammatik und Syntax sprechen. Wir wollen uns unter anderem über die Kodierung in Unicode, die Token und Bezeichner Gedanken machen.
2.3.1 Textkodierung durch Unicode-Zeichen  
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 auch zum erweiterten Zeichensatz. Da mit 16 Bit etwa 65.000 Zeichen kodiert werden können, sind auch alle wichtigen Zeichensätze für andere Schriftsprachen kodiert. 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.
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.1
2.3.2 Unicode-Tabellen unter Windows  
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.

Hier klicken, um das Bild zu Vergrößern
Abbildung 2.1 Zeichentabelle unter Windows XP
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.
2.3.3 Bezeichner  
Für Variablen (und damit Konstanten), Methoden, Klassen und Schnittstellen werden Bezeichner 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.
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 Bezeichner muss mit einem Unicode-Buchstaben beginnen. Dies sind Unicode-Zeichen zum Beispiel aus dem Bereich »A« bis »Z« und »a« bis »z« (nicht beschränkt auf lateinische Zeichen) sowie »_« und »$«.2 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.
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
|
raphaelIstLieb
|
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 Worter 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.
2.3.4 Reservierte Schlüsselwörter  
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:
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
|
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 zur Zeit nicht von Java benutzt werden, können doch keine Variablen dieses Namens definiert werden.
2.3.5 Token  
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.
Problematisch wird es in einer Sprache immer dann, wenn der Compiler die Token nicht voneinander unterscheiden kann. Daher fügen wir Trennzeichen (engl. White-Spaces), 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.
2.3.6 Semantik 
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.
1Mit 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.
2Ob ein Zeichen ein Buchstabe ist, verrät uns die Funktion Character.isJavaLetter().
3Siehe dazu Kapitel 3.9 (Keywords) der Sprachdefinition unter http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html.
|