Die ersten 256 Zeichen des Unicode sind identisch mit der ASCII-Variante
Latin-1.
Die meisten anderen Zeichen sind mit unseren Editoren nicht darstellbar,
daher gibt es eine Escape-Schreibweise:
\uddd (d ist Hexadezimalziffer)
Buchstabe (einschließlich _ und $), gefolgt von Buchstaben und Ziffern.
Wegen Unicode umfassen Buchstaben und Ziffern jedoch alle erdenklichen
Zeichen fast aller geschriebenen Sprachen.
abstract | double | int | static |
boolean | else | interface | super |
break | extends | long | switch |
byte | final | native | synchronized |
case | finally | new | this |
catch | float | null | throw |
char | for | package | throws |
class | goto * | private | transient * |
const * | if | protected | try |
continue | implements | public | void |
default | import | return | volatile |
do | instanceof | short | while |
Mit * markierte Schlüsselwörter sind reserviert aber (noch) nicht
verwendet.
Ganze Zahlen:
byte | 8-bit 2er Komplement | Byte |
short | 16-bit 2er Komplement | Kurz-Integer |
int | 32-bit 2er Komplement | Integer |
long | 64-bit 2er Komplement | Lang-Integer |
Fließpunktzahlen
float | 32-bit IEEE 754 | Einfachpräzision |
double | 64-bit IEEE 754 | Doppelpräzision |
Andere Typen
char | 16-bit Unicode-Zeichen | Buchstabe |
boolean | wahr oder falsch | Boolescher Wert |
Ganze Zahlen:
Oktaldarstellung | 052 |
Dezimaldarstellung | 42 |
Hexadezimaldarstellung | 0x2A |
Fließpunktzahlen
Vier Schreibweisen:
Digits . [Digits] [Expo] [FloatSuffix] z.B. 3.1E4 . Digits [Expo] [FloatSuffix] z.B. .1F Digits Expo [FloatSuffix] z.B 17e12 Digits [Expo] FloatSuffix z.B. 0F
Ohne ``FloatSuffix'' ist der Typ double.
Buchstaben
Buchstaben-Literale werden in einfache Anführungszeichen eingeschlossen: 'p'.
Die folgenden Escape-Sequenzen sind definiert:
![]() |
newline | ![]() |
Tabulator |
![]() |
backspace | ![]() |
return |
![]() |
form feed |
![]() |
der Backslash selbst |
![]() |
single quote | ![]() |
double quote |
![]() |
Oktalwertdarstellung |
Boolesche Werte
entweder true oder false.
Form:
Modifier Type Identifier_List
Modifier sind
public | |||
private | static | synchronized | |
protected |
Diese Reihenfolge wird empfohlen, im Prinzip ist sie aber beliebig.
Es gibt 7 Arten von Variablen:
Typ | Default |
boolean | false |
char | \u0000 |
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0 |
double | 0.0 |
Klasse, Interface, Array | null |
Lokale Variablen in Methoden, Konstruktoren und Initialisierungsblöcken
bekommen keine Default-Werte!
Verwendung führt zu Fehler:
Beispiel:
class UnInit { static public void main(String av[]) { double d; if (true) d=9.9; else ; System.out.println(d); // FEHLER } }
liefert die Compiler-Fehlermeldung
Variable d may not have been initialized
Durch seine Deklaration lebt jeder Bezeichner in einem bestimmten Namensraum. Alle Bezeichner in einem Namensraum müssen verschieden sein.
Wird ein Bezeichner angewendet, muß festgestellt werden, in
welchem Namensraum er lebt um dann auf seine
deklarierten Eigenschaften zugreifen zu können.
Der gleiche Bezeichner darf in verschiedenen Namensräumen leben:
class Reuse { Reuse Reuse(Reuse Reuse) { Reuse: for (;;) { if (Reuse.Reuse(Reuse) == Reuse) break Reuse; } return Reuse; } }
Namensräume in Java
Die Namensräume sind geschachtelt, dh. Deklarationen in inneren
Strukturen können die Deklarationen in äußeren Strukturen verdecken.
Beispiel:
der Name eines Konstruktorparameters überdeckt den Namen einer Instanzvariable.
class MyClass { T myattr; MyClass (T myattr) { this.myattr = myattr; } }
Ausnahme:
Die Schachtelung von Blöcken und for-Schleifen kann nicht dazu benutzt werden, Bezeichner aus äußeren Blöcken, for-Schleifen und Methoden-Parameter zu überdecken.
class Nesti { static public void main(String a[]) { double d = 9.9; for (int i = 0; i < 10; i++) { int d; // FEHLER boolean a; // FEHLER char i; // FEHLER ... } } }
liefert
'd' is already defined in this method. 'a' is already defined in this method. 'i' is already defined in this method.
Ziel:
Diese Bezeichnerkonventionen sind Empfehlungen, man muß sich nicht sklavisch daran halten.
So sind z.B. sin und cos aus der Bibliothek
java.lang.Math Bezeichner, die gegen die Java-Konventionen verstoßen,
sie sind aber üblich.
Klassen und Interfaces
Beispiele:
ClassLoader BufferedInputStream HalloWelt
Methoden
Beispiele:
sayHello() printDataFile()
Zusatzregeln:
Konstanten
Beispiele:
MAX_VALUE MIN_TEMP
Variablen und Parameter
Beispiele:
buf cp len out
Präzedenz beschreibt die ``Bindungskraft'' von Operatoren.
So ist
3 * 5 - 3
12 und nicht 6, und
(i >= min && i <= max)
prüft ob i zwischen min und max liegt.
Sind zwei Operatoren gleicher Präzedenz in einem Ausdruck benachbart,
so bestimmt die Assoziativität, welcher von beiden zuerst ausgewertet
wird.
a + b + c
bedeutet (da die Addition linksassoziativ ist)
(a + b) + c
Die Operatorpräzedenzen absteigend geordnet:
Operator-Art | Operatoren |
Postfix-Operator | [] . (params ) expr ++ expr - |
Unärer Operator | ++expr -expr +expr -expr ! ~ |
Erzeugung oder Typ-Cast | new (type )expr |
Multiplikation | * / % |
Addition | + - |
Shift | << >> >>> |
Relational | < > <= >= instanceof |
Gleichheit | == != |
bitweises AND | & |
bitweises XOR | ^ |
bitweises OR | | |
logisches AND | && |
logisches OR | || |
Bedingung | ? : |
Zuweisung | = += -= *= /= %= >>= <<= |
>>>= &= ^= = |= |
Alle Wertzuweisungen sind rechtsassoziativ, die anderen binären
Operatoren sind linksassoziativ.
Mit Klammern kann die Operatorbindung beeinflußt werden:
while ((v = stream.next()) != null) { ... }
Java garantiert, daß die Operanden von Operatoren von links nach rechts ausgewertet werden.
Im Ausdruck
x + y + z
wird also niemals y vor x oder z vor x oder y ausgewertet.
Auswertungsreihenfolge ist natürlich
nur beobachtbar für Operanden mit Seiteneffekten,
z.B.
Außer bei den Operatoren &&, || und ?:
werden stets alle Operanden ausgewertet, bevor eine Operation ausgeführt wird.
Wir unterscheiden:
Hier unterscheiden wir die Typanpassung für Grundtypen und die für Referenztypen.
Bei Grundtypen wird implizit zwischen zwei Typen konvertiert, wenn
der Bereich des Zieltyps größer oder gleich ist.
Zum Beispiel:
Bei Referenztypen wird implizit konvertiert zwischen einem Typ
T und seinen Obertypen.
Explizite Casts erlauben Typanpassungen, bei denen der Zieltyp den kleineren Wertebereich umfaßt:
double d = 7.88; long l = (long) d;
Explizite Casts also z.B.
Bei solchen Typanpassungen kann man Genauigkeit verlieren:
short s = -134; byte b = (byte) s;
Die vorderen Bits gehen verloren: b hat den Wert 122.
Für Referenztypen erlauben explizite Casts Typumwandlungen entgegen der
Klassenhierarchie, also z.B. vom Obertyp zum Untertyp
Solche Typumwandlungen heißen
Sie erfordern einen Laufzeittest, ob das aktuelle Objekt tatsächlich
für den Zieltyp zulässig ist. Wenn nicht: ClassCastException.
Beispiel:
class Ober{} class Unter extends Ober{} public class Classcast { public static void main(String argv[]) { Ober objo = new Ober(); Unter obju = (Unter) objo; } }
liefert Laufzeit-Fehler
java.lang.ClassCastException: Ober
Mögliche Down-Casts:
Diese Down-Casts erfordern Laufzeittests, ob der tatsächliche Wert für
den Zieltyp zulässig ist.
String Konvertierung
Es gibt Typanpassungen von jedem Typ (einschließlich Null) nach
String.
Verbotene Typanpassungen:
+ | op1 + op2 | Addiert op1 und op2 |
- | op1 - op2 | Subtrahiert op2 von op1 |
* | op1 * op2 | Multipliziert op1 mit op2 |
/ | op1 / op2 | Dividiert op1 durch op2 |
% | op1 % op2 | Berechnet den Rest der Division op1 durch op2 |
Außerdem zwei unäre Operatoren
+ | + op1 | Unäres Plus (aus Symethrie-Gründen) |
- | - op1 | Unäres Minus, Negation |
Java rechnet ganzzahlig in Zweierkomplement-Arithmetik.
Nichts kann über- oder unterlaufen.
Für die Gleitpunkt-Arithmetik wird
eine Untermenge des IEEE 754-1985-Standards benutzt.
Es gibt ausgezeichnete Werte für +, -
und
NaN (not a number) und Rechenregeln dazu.
+ wird zur String-Konkatenation verwendet:
String boo = "boo"; String cry = boo + "hoo"; cry += "!"; System.out.println(cry);
liefert
boohoo!
Die implizite Konvertierung nach String gibt es nur im Zusammenhang mit dem Operator +:
String s; s = '@' + s + 3.14;
aber z.B. nicht bei der Parameterübergabe an String-Parameter.
++ | op++ | Erhöht op um 1, liefert Wert vor Inkrement |
++ | ++op | Erhöht op um 1, liefert Wert nach Inkrement |
- | op- | Erniedrigt op um 1, liefert Wert vor Dekrement |
- | -op | Erniedrigt op um 1, liefert Wert nach Dekrement |
Vergleichsoperatoren
> | op1 > op2 | op1 ist größer als op2 |
>= | op1 >= op2 | op1 ist größer oder gleich op2 |
< | op1 < op2 | op1 ist kleiner als op2 |
<= | op1 <= op2 | op1 ist kleiner oder gleich op2 |
== | op1 == op2 | op1 und op2 sind gleich |
!= | op1 != op2 | op1 und op2 sind nicht gleich |
Diese Operatoren liefern Boolesche Werte.
Logische Operatoren
&& |
op1 && op2 |
op1 und op2 sind beide true |
|| | op1 || op2 | op1 oder op2 ist true |
! | ! op | op ist false |
Diese Operatoren werten ihre rechten Operanden nicht aus, wenn der linke bereits das Ergebnis bestimmt ( Boolesche Kurzauswertung).
Der bedingte Operator ?:
Erlaubt Ausdrücke, die abhängig von einer Bedingung einen von zwei Werten liefern:
val = userSetIt ? usersVal : defaultVal;
Der Typ eines der Ausdrücke muß dem Typ des anderen Ausdrucks ohne expliziten Cast zuweisbar sein. Der allgemeinere Typ der beiden bestimmt das Ergebnis. Dies gilt auch für Referenztypen.
>> | op1 >> op2 | Rechtsshift von op1 um op2 Stellen |
>>> | op1 >>> op2 | dto. aber von links 0 nachziehen |
<< | op1 << op2 | Linksshift von op1 um op2 Stellen |
& |
op1 & op2 |
bitweises UND |
| | op1 | op2 | bitweises ODER |
^ |
op1 ^ op2 |
bitweises Exclusiv-Oder |
~ |
~op2 |
bitweises Komplement |
Bitweise Operationen dürfen nur auf ganzen Zahlen und Booleschen
Werten ausgeführt werden.
+= | op1 += op2 | op1 = op1 + op2 |
-= | op1 -= op2 | op1 = op1 - op2 |
*= | op1 *= op2 | op1 = op1 * op2 |
/= | op1 /= op2 | op1 = op1 / op2 |
%= |
op1 %= op2 |
op1 = op1 % op2 |
&= |
op1 &= op2 |
op1 = op1 &= op2 |
|= | op1 |= op2 | op1 = op1 | op2 |
^= |
op1 ^= op2. |
op1 = op1 ^ op2 |
<<= | op1 <<= op2 | op1 = op1 << op2 |
>>= | op1 >>= op2 | op1 = op1 >> op2 |
>>>= | op1 >>>= op2 | op1 = op1 >>> op2 |