Der Datentyp eines Attributes bestimmt, welche Informationen in einem Attribut abgelegt werden dürfen. Wird als Datentyp eines Attributes der Name einer Klasse angegeben, dürfen nur Objekte dieser Klasse als konkrete Werte diesem Attribut zugewiesen werden. Mit den sogenannten primitiven Datentypen gibt es in Java allerdings eine Menge von sehr einfachen Datentypen, die nicht durch eine eigene Klasse beschrieben werden.
Primitive Datentypen werden eingesetzt um Wahrheitswerte (true, false), ganze Zahlen (1, 12, 13131),
Fließkommazahlen (1.123, 21234.1232) und einzelne Zeichen (t, w, f, d) zu speichern. Primitive
Datentypen sind einfache Standard-Datentypen, die es auch in anderen Programmiersprachen gibt.
Übersicht über die primitiven Datentypen in Java:
| Art der gespeicherten Werte |
Schlüsselwort in Java |
Beschreibung | Beispiele |
| Wahrheitswerte | boolean |
Kann entweder true oder false sein. Weitere Werte sind nicht erlaubt. | true |
| Ganze Zahl | byte |
8Bit-Wertebreich von -128 bis 127 | -123, 0,23, 120 |
short |
16Bit-Wertebreich von -32.768 bis 32.767 | -23000, 0, 13231 |
|
int |
32Bit-Wertebreich von -2.147.483.648 bis 2.147.483.647 | -12332123, 234, |
|
long |
64Bit-Wertebreich von -9.223.372.036.854.775.808 bis 9.223.372.036.854.775.807 | -8347829790645, |
|
| Fließkommazahl | float |
32Bit-Wertebreich von 1,40239846*10^-45 bis 3,40282347*10^38 | 1.87236f (Einfache Zahl mit Komma |
double |
64Bit-Wertebreich von 4,94065645841246544*10^-324 bis 1,79769131486231570*10^308 |
1.87236d (Einfache Zahl mit Komma |
|
| Schriftzeichen (Character) |
char |
Ein einzelnes Unicode-Zeichen. Umfasst neben Ziffern, Buchstaben und Symbolen auch Steuerzeichen wie Leerzeichen, Tabulator oder Zeilenumbruch. |
'A' (= Buchstabe A) |
Für ganze Zahlen wird in der Regel der Datentyp int verwendet.
Ein weiterer häufig verwendeter Datentyp ist String. Er wird zur Speicherung von Zeichenketten verwendet. String ist kein primitiver Datentyp, sondern wird durch eine eigene Java-Klasse beschrieben. Dennoch kann String wie ein primitiver Datentyp Attributen zugewiesen werden.
| Art der gespeicherten Werte |
Schlüsselwort in Java |
Beschreibung | Beispiele |
| Zeichenketten | String |
Wird zum Speichern von beliebig langen Zeichenketten verwendet. Ist kein primitiver Datentyp. Die Klasse String bietet viele bereits vorhandene Methoden für die Bearbeitung von Zeichenketten. |
"online", "Herr Koch", |
Mit Variablen bietet Java die Möglichkeit, konkrete Werte im Speicher der Anwendung abzulegen. Damit können z.B. Ergebnisse von Berechnungen kurzzeitig gespeichert werden, die als Eingabeparameter für weitere Berechnungen benötigt werden.
Vergleichbar mit einem Attribut muss zur Deklaration einer Variable der Datentyp und der Name einer Variable festgelegt werden. Abgeschlossen wird die Deklaration mit einem Semikolon ";". Anders als bei Attrbiuten können Variablen jedoch nur innerhalb des Methodenrumpfes verwendet werden. Daher benötigt sie keinen Sichtbarkeitsmodifikator. Nachdem Variablen deklariert worden sind, können sie innerhalb der Methode verwendet werden. Das bedeutet auch, dass ihr erst dann ein konkreter Wert zugewiesen werden kann, nachdem die Variable deklariert wurde.
Deklaration und Zuweisung von Variablen:
public void rechnerei() {
int zahl1;
byte zahl2;
float zahl3;
char einZeichen;
String zeichenkette;
zahl1 = 234;
zahl2 = 123;
zahl3 = 123.4f;
einZeichen = 'E';
zeichenkette = "Das ist eine Zeichenkette";
}
Im ersten Block werden Variablen deklariert (z.B. zahl1 vom Typ Integer), im zweiten Block werden den Variablen Werte zugewiesen
(z.B. der Wert E der Variablen einZeichen). Die Zuweisung wird durch das Gleichheitszeichen "=" ausgedrückt. Links von "="
steht der Name der Variable, rechts von "=" der Wert, den die Variable erhalten soll.
Die Deklaration und Zuweisung von Variablen können auch innerhalb einer Anweisung erfolgen:
public void rechnerei() {
int zahl1 = 234;
byte zahl2 = 123;
float zahl3 = 123.4f;
char einZeichen = 'E';
String zeichenkette = "Das ist eine Zeichenkette";
}
Operatoren ermöglichen das Rechnen und Verändern von in Variablen und Attributen gespeicherten Werten. Die Programmiersprache Java unterstützt dafür eine Menge arithmetischer und logischer Operatoren. Generell wird der Datentyp des Ergebnisses eines Operators durch den Operanden, der den größten Wertebereich hat, bestimmt.
Die wichtigsten arithmetischen Operatoren:
| Ausgeführte Operation | Operator | Anwendbar auf die Datentypen | Beispiel |
| Inkrement; erhöht eine Variable um den Wert 1 |
++ | Ganze Zahlen, Fließkommazahlen | int a = 3; |
| Arithmetische Addition; der Ergebnistyp der Berechnung entspricht dem des Operanden mit dem größten Wertebereich (z.B. int + int = int, int + long = long) |
+ | Ganze Zahlen, Fließkommazahlen | int c, d, e; |
| Arithmetische Subtraktion | - | Ganze Zahlen, Fließkommazahlen | int e = 3; |
| Arithmetische Multiplikation | * | Ganze Zahlen, Fließkommazahlen | int c, d; |
| Arithmetische Division; berechnet Quotienten aus Dividend und Divisor |
/ | Ganze Zahlen: Sind beide Operanden ganze Zahlen, wird vom Ergebnis der Teil nach dem Komma abge- schnitten. Fließkommazahlen: Ist mindestens ein Operand eine Fließkommazahl, wird das Ergebnis auch eine Fließkommazahl und nicht gerundet. |
int h = 4; |
| Rest (auch: Restwert-Operator); berechnet den Rest der arithmetischen Division |
% | Ganze Zahlen, Fließkommazahlen | int k = 11; |
Im Unterschied zu arithmetischen Operatoren werten logische Operatoren Ausdrücke zu wahr (true) oder falsch (false) aus. Sie werden daher häufig zur Steuerung von Kontrollstrukturen eingesetzt. Der Ergebnistyp von logischen Operatoren ist immer boolean.
| Ausgeführte Operation | Operator | Anwendbar auf die Datentypen | Beispiel |
| Logisches Komplement (Negation); ändert den Wahrheitswert des Operanden |
! | boolean | boolean b1; |
| Logisches UND; liefert true, wenn beide Operanden true sind |
&& | boolean | boolean b3; |
| Logisches ODER; liefert true, wenn einer der beiden Operanden true ist |
|| | boolean | boolean b6; |
| Exklusiv-ODER; liefert true, wenn ein Operand true und ein Operand false ist |
^ | boolean | boolean b9; |
Vergleichsoperatoren vergleichen Ausdrücke miteinander und liefern als Ergebnistyp boolean. Das heißt, sie liefern entweder wahr (true) oder falsch (false) zurück. Ebenso wie logische Operatoren werden Vergleichsoperatoren häufig zur Steuerung von Kontrollstrukturen eingesetzt.
| Ausgeführte Operation | Operator | Anwendbar auf die Datentypen | Beispiel | |
| Gleich- heit |
Primitive Datentypen: liefert true, wenn die Werte der Operanden gleich sind |
== | Primitive Datentypen | int z1, z2; |
| Referenzdatentypen: liefert true, wenn in beiden Operanden die Referenz auf dasselbe Objekt enthalten ist |
Referenzdatentypen | Kunde kunde1, kunde2; |
||
| Ungleich- heit |
Primitive Datentypen: liefert true, wenn die Werte der Operanden nicht gleich sind |
!= | Primitive Datentypen | int z3, z4; |
| Referenzdatentypen: liefert true, wenn in beiden Operanden unterschiedliche Referenzen enthalten sind |
Referenzdatentypen | Kunde kunde3, kunde4; |
||
| Kleiner als liefert true, wenn der Wert des linken Operanden kleiner ist verglichen mit dem Wert des rechten Operanden |
< | Ganze Zahlen, Fließkommazahlen |
int z5, z6; |
|
| Kleiner gleich liefert true, wenn der Wert des linken Operanden kleiner oder gleich ist verglichen mit dem Wert des rechten Operanden |
<= | Ganze Zahlen, Fließkommazahlen |
int z5, z6; |
|
| Größer als liefert true, wenn der Wert des linken Operanden größer ist verglichen mit dem Wert des rechten Operanden |
> | Ganze Zahlen, Fließkommazahlen |
int z7, z8; |
|
| Größer gleich liefert true, wenn der Wert des linken Operanden größer oder gleich ist verglichen mit dem Wert des rechten Operanden |
>= | Ganze Zahlen, Fließkommazahlen |
int z7, z8; |
|
| Typvergleich liefert true, wenn der Datentyp des linken Operanden gleich dem gegebenen Datentypen im rechten Operanden ist |
instanceof | Referenzdatentypen | Kunde k1; |
|
Besondere Prüfoperatoren sind die Prüfung auf Gleichheit (==) und die Prüfung auf
Ungleichheit (!=). Denn bei diesen Operatoren bestimmen die Operanden wie verglichen wird. Dabei unterscheidet sich
der Vergleich zwischen primitiven Datentypen und Referenzdatentypen grundsätzlich. Sind beide Operanden
primitive Datentypen, so werden direkt die Werte der Operanden verglichen.
int z1, z2;
boolean e1;
z1 = 3;
z2 = 3;
e1 = z1 == z2;
System.out.println(e1);
In diesem Fall hat e1 den Wert true.
Für den Fall, dass Referenzdatentypen verglichen werden sollen, vergleicht der Operator "==" nicht den
tatsächlichen Inhalt der zu vergleichenden Objekte. Es wird vielmehr nur verglichen, ob beide Operatoren
dieselben Objekte referenzieren, das heißt, auf das gleiche Objekt "zeigen". Im untenstehenden Code wird k3 und k4
jeweils ein neu erzeugtes Objekt zugewiesen. In k3 ist die Referenz auf das erste Objekt "Kunde" gespeichert, in k4
die Referenz auf das zweite Objekt "Kunde". Der Vergleich auf "Referenzgleichheit" von k3 und k4 liefert damit den
Wert false.
Kunde k3, k4;
boolean e1;
k3 = new Kunde();
k4 = new Kunde();
e1 = k3 == k4;
System.out.println(e1);
Im folgenden Codebeispiel wird der Variablen k4 kein neu erzeugtes Objekt mehr zugewiesen. Der Variablen k4 wird
nun exakt der gleiche Wert zugewiesen, der in k3 gespeichert ist. Da der Wert von k3 eine Referenz auf ein Objekt vom
Typ "Kunde" ist, hat k4 nach der Anweisung k4 = k3 genau dieselbe Referenz wie der Wert k3. Damit liefert die Operation
k3 == k4 das Ergebnis true.
Kunde k3, k4;
boolean e1;
k3 = new Kunde();
k4 = k3;
e1 = k3 == k4;
System.out.println(e1);
Darüber hinaus gibt es noch einen Operator, der häufig verwendet wird, um Zeichenketten miteinander zu verbinden, das heißt, mehrere Zeichenketten zu einer neuen zusammenzuführen (String-Konkatenation).
| Ausgeführte Operation | Operator | Anwendbar auf die Datentypen | Beispiel |
| Verketten von Zeichen (Konkatenation); Verketten von mehreren Zeichenketten zu einer neuen Zeichenkette |
+ | String | String s1, s2, s3, s4; |
Beim Ablauf eines Programms wird ein Methodenrumpf von oben nach unten durchgearbeitet. Bei der Implementierung von Algorithmen und Geschäftsregeln ist es jedoch häufig notwendig, konkrete Anweisungen nur beim Vorliegen ganz bestimmter Bedingungen durchzuführen. Weiterhin ist es häufig notwendig, dieselben Anweisungen hintereinander für eine Menge von Werten auszuführen.
Das bedingte oder kontrollierte wiederholte Ausführen von Anweisungen wird durch sogenannte Kontrollstrukturen ermöglicht. Die wichtigsten von Java unterstützten Kontrollstrukturen sind:
Die bedingte Verzweigung wird verwendet, um die konkrete Stelle, mit der das Programm fortgesetzt wird, anhand
einer Bedingung zu prüfen.
if (Bedingung) {
Anweisung1;
}
else {
Anweisung2;
}
Die Bedingung muss dabei ein Ausdruck sein, der zu true oder false ausgewertet werden kann. Die Anweisung1 wird nur dann
ausgeführt, wenn die Bedingung true ist. In diesem Fall wird Anweisung2 nicht ausgeführt. Anweisung2 wird
hingegen nur dann ausgeführt, wenn die Bedingung false ist und damit Anweisung1 nicht ausgeführt wurde. Der
else-Teil in bedingten Verzweigungen ist optional.

Bei einer bedingten Verzweigung werden entweder die Anweisungen im "if-Block" ausgeführt oder die Anweisungen im
"else-Block". Niemals jedoch beide Blöcke.
Beispiel einer einfachen bedingten Verzweigung:
In einer erweiterten if-else-Verzweigung wird nicht nur eine Bedingung geprüft, bevor der else-Block
abgearbeitet wird, sondern mehrere sich gegenseitig ausschließende Bedingungen. Die Struktur einer erweiterten
if-else-Verzweigung in Java sieht wie folgt aus:
if (Bedingung1) {
Anweisung1;
}
else if (Bedingung2) {
Anweisung2;
}
else {
Anweisung3;
}
Auch bei einer erweiterten if-else-Vezweigung wird jeweils nur ein Block abgearbeitet.
Neben den Verzweigungen sind die sogenannten Schleifen eine weitere wichtige Kontrollstruktur. Schleifen
ermöglichen die mehrfache Ausführung von gleichen Anweisungen hintereinander. Die Anzahl der
Schleifendurchläufe wird von einer Einhaltung einer Schleifenbedingung (auch: Laufbedingung, Abbruchbedingung)
bestimmt. Grundsätzlich können drei verschiedene Schleifenarten unterschieden werden:
Die while-Schleife prüft zuerst die Schleifenbedingung. Wenn die Bedingung erfüllt ist, werden die
Anweisungen der Schleife ausgeführt. Andernfalls werden die Anweisungen der Schleife übersprungen. Nach der
Ausführung der Anweisungen der Schleife wird erneut die Bedingung geprüft. Wird diese zu false ausgewertet,
ist die Schleife beendet. Bei einer Auswertung der Bedingung zu true werden die Anweisungen der Schleife erneut
durchlaufen. Die Struktur einer while-Schleife sieht folgendermaßen aus:
while (Bedingung) {
Anweisungen;
}
Die while-Schleife wird auch kopfgesteuerte Schleife genannt, denn bereits vor dem ersten Ablauf wird die Bedingung
bereits geprüft. Wird sie dabei zu false ausgewertet, wird die komplette Schleife übersprungen.
Die do-while-Schleife ist eine fußgesteuerte while-Schleife. Die Anweisungen der Schleife werden in jedem Fall
mindestens einmal ausgeführt. Erst dann wird die Schleifenbedingung geprüft. Wenn die Bedingung erfüllt
ist, werden die Anweisungen der Schleife wiederholt ausgeführt. Andernfalls wird die Schleife beendet. Die Struktur
einer do-while-Schleife sieht folgendermaßen aus:
do {
Anweisungen;
} while (Bedingung);

Im Unterschied zur while-Schleife und zur do-while-Schleife sind bei der for-Schleife die Initialisierung, Bedingungsprüfung und das Ändern der Zählvariablen Elemente des Schleifenkopfes. Genauso wie die while-Schleife ist die for-Schleife eine kopfgesteuerte Schleife, das heißt, vor dem erstmaligen Ausführen der Schleife wird geprüft, ob die Bedingung erfüllt ist.
Die Struktur einer for-Schleife kann folgendermaßen dargestellt werden:
for (Initialisierung; Bedingung; Schleifenfortschaltung) {
Anweisungen;
}
Das Ablaufschema einer for-Schleife kann wie folgt beschrieben werden:
Dabei wird deutlich, dass im Anweisungsblock keine Steueranweisungen der Schleife, wie zum Beispiel das Ändern
der Zählvariablen, implementiert sind:
Kontrollstrukturen können in ihren Anweisungsblöcken selbst wieder Kontrollstrukturen enthalten. Daher können auch Schleifen ineinander geschachtelt werden.
Zur logischen Strukturierung der Klassen innerhalb eines Projektes sowie zur Aufteilung der Aufgaben im Entwicklungsteam wird die Menge aller Klassen in verschiedene Pakete unterteilt. Klassen mit ähnlichen Funktionen und Klassen, die stark voneinander abhängen, werden gleichen Paketen zugeordnet. Die Zuordnung zu Paketen hat Auswirkungen auf den Speicherort der Klasse und auf die Zugriffsberechtigungen auf Methoden anderer Klassen.
Pakete lassen sich mit Verzeichnissen des Dateisystems eines Computers vergleichen. Verzeichnisse dienen als Mittel zur Strukturierung von Dateien und speichern selber keine Informationen. Jede Datei wird in genau einem Verzeichnis gespeichert. Verzeichnisse können Unterverzeichnisse enthalten. Dateien können jedoch keine weiteren Dateien oder Verzeichnisse enthalten. Genau so verhält es sich mit Paketen und Klassen anstelle von Verzeichnissen und Dateien.

Die erste Quelltextzeile in einer Java-Klasse enthält immer die Angabe des Pakets, in dem sich die Klasse
befindet.
package onlineshop.abwicklung;
public class Bestellung {
...
}
Der Speicherort der Datei ergibt sich aus dem Paket einer Klasse. Dabei wird für jedes Paket eines Programms ein Verzeichnis angelegt. Die Datei mit der Java-Klasse muss sich in dem Verzeichnis des Pakets befinden. Für die Klasse "Kunde" im Paket "onlineshop.nutzer" muss es eine Datei "onlineshop/nutzer/Kunde.java" geben.
Klassennamen müssen innerhalb eines Pakets eindeutig sein. Der für die Java-Laufzeitumgebung vollständige Name einer Klasse (der sogenannte "qualifizierte Name") ergibt sich aus dem Paket der Klasse und dem Namen der Klasse.
Mit Hilfe der Sichtbarkeitsmodifikatoren wird die Sichtbarkeit von Klassen, Attributen und Methoden und damit Zugriffsmöglichkeiten von anderen Klassen festgelegt. In Java gibt es folgende vier Sichtbarkeitsmodifikatoren, die auf die Elemente Klasse, Attribut und Methode angewendet werden können:
| Sichtbarkeitsmodifikator | Beschreibung | Anwendbar auf | Beispiel |
public |
Das Element ist für alle Klassen des Programms sichtbar. |
Klassen, Attribute, Methoden | public class Bestellung {} |
| (nichts) | Das Element ist nur im gleichen Paket sichtbar. | Klassen, Attribute, Methoden | class Bestellung {} |
protected |
Das Element ist nur im gleichen Paket oder abgeleiteten Klassen sichtbar. |
Attribute, Methoden | protected void berechneSumme() {} |
private |
Das Element ist nur für Elemente der gleichen Klasse sichtbar. |
Attribute, Methoden | private void berechneSumme() {} |
Obwohl Java dem Entwickler die Möglichkeit gibt, die Sichtbarkeit von Attributen so festzulegen, dass ein direkter Zugriff durch andere Klassen erfolgen kann, sollten Attribute außer in gut begründeten Ausnahmefällen immer mit der Sichtbarkeit "private" versehen werden.