Das Java Tutorium
1. Datentypen, Variablen & Co.
Kurzer Überblick:
1.1 Was ist eine Variable?
1.2 Wozu haben Variablen Datentypen?
1.3 Was gibt es für Datentypen?
1.4 Variablen eingesetzt...
1.5 Referenztypen
1.6 Arrays
1.7 Strings
1.8 Typkonvertierung
1.9 Sichtbarkeit (Scope), Lebensdauer
1.1 Was ist eine Variable?
Beim Programmieren ist es enorm wichtig zu bestimmten Zeitpunkten Daten im Hauptspeicher abzulegen. Im letzten Kapitel haben wir ein Roboter Beispielalgorithmus gesehen, der eine Eingabe <input> benutzt hat. Dieser <input> war eine Variable die zwischenzeitlich im Speicher abgelegt wurde. Dort hätte sie verändert und ausgelesen werden können. Also immer wenn man Daten speichern möchte, benutzt man Variablen. Dieses Speichern hat natürlich nichts mit dauerhaftem Speichern auf z.B. der Festplatte zu tun...
In Java gibt es drei Variablentypen:
-
Objektvariablen (Attribute) sind Variablen eines erzeugten Objekts und werden innerhalb der Klasse definiert. Verschiedene Objekte gleichen Typs können in ihren Objektvariablen unterschiedliche Daten speichern.
-
Klassenvariablen gelten für jedes Objekt gleich, d.h. wenn ein Objekt den Inhalt einer Klassenvariablen ändert, ist der Inhalt für ein anderes Objekt ebenfalls geändert. Klassenvariablen werden mithilfe eines vorangestellten "static" definiert.
-
lokale Variablen gelten nur innerhalb eines Blocks - also z.B. innerhalb von Methoden oder Schleifen.
Nun eigentlich kann man das noch gar nicht so wirklich verstehen, wenn man von Objektorientierung keine Ahnung hat, aber die verschiedenen Variablentypen jetzt vorzustellen, hielt ich für sinnvoller...
Allen Variablen gemein ist, dass man ihnen stets bestimmte Werte zuweisen kann. Und zwar sowohl zu Beginn, als auch während des Programms. Wenn das Programm also irgendetwas berechnet, kann es dazu Variablen auslesen, schreiben, verändern - je nach Lust und Laune
Kann man jetzt in jede Variable einfach irgendwelche Daten schreiben? Nein!

- das geht nicht, dazu gibt es in Java (und in jeder Programmiersprache mehr oder weniger auch) sogenannte Datentypen.
1.2 Wozu haben Variablen Datentypen?
Nun - es gibt auch in der Realität verschiedene Formen von Daten. Text ("Hallo Welt!"), einzelne Zeichen ('a', 'x'), ganze Zahlen (3, 7), Gleitkommazahlen (1.41) und soetwas wie Wahrheitswerte: "Die Straße ist nass!" Antwort: wahr oder halt falsch ... (true, false). Diese in der Realität vorkommenen Datenformen werden in Java als Datentypen bezeichnet.
Man unterscheidet in Java zwischen
primitiven Datentypen und den
Rerenztypen (dazu gleich mehr...). Alle Datentypen besitzen einen bestimmten Wertebereich. Also einen Bereich den die Werte (von...bis) annehmen dürfen bzw. können. Dieser Wertebereich ist natürlich abhängig von der Länge des Datentyps, also wieviel Speicher für einen Wert im Vorfeld reserviert werden muss! Man sollte sich also überlegen wie groß die Werte so werden können und danach entscheiden welcher Datentyp gebraucht wird. Wenn man mit den primitiven Datentypen alleine nicht mehr hinkommt, bietet Java natürlich noch Kniffe an trotzdem mit großen Zahlen rechnen zu können...(dazu aber sehr viel später mehr *g*). Darüberhinaus besitzt jeder Datentyp einen Standardwert, also der Wert den eine Variable mit einem bestimmten Datentyp von vornherein annimmt.
1.3 Was gibt es für Datentypen?
Primitve Datentypen sind im Wesentlichen die oben genannten, konkret in Java folgende:
boolean (Wahrheitswerte)
Länge: 1 Byte
Wertebereich: true, false
Standardwert: false
Die einzigen Werte (Literale) die eine Variable des Typs boolean annehmen kann, sind also true oder false (wahr oder falsch). Dieser Datentyp ist hervorragend geeignet, wenn man nur genau zwei mögliche Werte für eine Variable vergeben braucht. Vom Prinzip her also ein einfach Schalter, den man an- und ausschalten kann.
char
Länge: 2 Byte (16 Bit)
Wertebereich: alle Unicode-Zeichen (insg. 2^16 == 65.536 verschiedene Zeichen)
Standardwert: \u0000 (das ist die 0 als Zeichen

)
Der Datentyp char ist die Möglichkeit in Java einzelne Zeichen zu speichern. Die Literale dieses Datentyps werden in einfachen Anführungszeichen geschrieben: 'a'. Darüberhinaus kann man Zeichen noch in der Form \uXXXX angeben, wobei die XXXX für 4 hexadezimale Ziffern stehen. Die entsprechende Codierung kann man einer gängigen Unicode-Tabelle entnehmen (der Windows Zeichentabelle e.g.).
Außerdem gibt es noch einige Spezialzeichen, wie etwa '\n' für Newline, also der neuen Zeile oder '\t' für das Tabulatortrennzeichen usw...
Integer
Die Integer-Typen umfassen insg. 4 primitive Datentypen:
byte
Länge: 1 Byte
Wertebereich: -2^7 ... 2^7-1 (die nach ^ kommende Zahl soll die Potenz darstellen... in diesem Fall geht der Wertebereich also von -128 bis +127 - also insg. 255 verschiedene Werte. Bei der Länge 1 Byte == 8 Bit, leicht zu errechnen: 2^8 - 1.
Standardwert: 0
Dieser Datentyp ist für zu erwartende kleine Integer-Zahlen geeignet, da mit 1 Byte noch relativ klein...
short
Länge: 2 Byte (16 Bit)
Wertebereich: -2^15...2^15-1
Standardwert: 0
Nur größer als byte - sonst identisch...
int
Länge: 4 Byte (32 Bit)
Wertebereich: -2^31...2^31-1 (das sind im positiven: 2.147.483.647 ...das ist schon relativ groß - aber viel mehr als 2 Milliarden darf man halt nicht verdienen *g*)
Standardwert: 0
int ist der typische Integerwert in Java. In den meisten Fällen wird man diesen Datentypen für die ganzen Zahlen verwenden.
long
Länge: 8 Byte (64 Bit)
Wertebereich: -2^63...2^63-1 (verdammt viel Schotter!

)
Standardwert: 0
Damit kann man schon einiges Speichern... benutzt aber natürlich auch verdammt viel Speicher!
Gleitkomma Zahlen/Floating-Point Numbers
Im Gegensatz zu den Integer-Zahlen können Gleitkommazahlen Dezimalstellen speichern. Die Gleitkommadarstellung ist aber nur eine näherungsweise Darstellung von den reellen Zahlen! Hingewiesen sei hier auf das Script zur Vorlesung Kapitel 3: Speicherung von Informationen.
float
Länge: 4 Byte (32 Bit)
Wertebereich: 1.4*10^-45 ... 3.4028235*10^38 (Genauigkeit von 7 Stellen, positiv&negativ)
Standardwert: 0.0
Der "kleine" Gleitkommawert...
double
Länge: 8 Byte (64 Bit)
Wertebereich: 4.9*10^-324 ... 1.7976931348623157*10^308 (Genauigkeit von 16 Stellen, positiv&negativ)
Standardwert: 0.0
Dieser Datentyp ist schon etwas genauer und es lassen sich schon recht kleine und auch recht große Zahlen damit darstellen... Wie sich die Wertebereiche ergeben kann man übrigens ebenfalls aus dem oben erwähntem Script erkennen, ist aber für das eigentliche Vorhaben, nämlich das Programmieren nicht wirklich notwendig zu verstehen

- aber vielleicht interessiert's den ein oder anderen.
Der Exponent einer Gleitkommazahl kann übrigens als Literal so angegeben werden: 3e3 und entsprich damit 3*10^3 also 3000.0 oder aber z.B. 3e-3 ist dann 3*10^-3 == 0.0030 oder auch 3/1000.
Diese Literale gelten für Double-Datentypen und können nicht für float verwendet werden. Wenn man float-Literale angeben möchte, muss man hinter die Zahl ein f anfügen! Dem Literal kann natürlich ebenfalls ein Vorzeichen hinzugefügt werden...
Man mag gemerkt haben, dass ich über die Zeichenketten noch kein Wort verloren hab. Bislang gab es nur einzelne Zeichen vom Datentyp char. Zeichenketten bzw. Strings werden aus gutem Grund etwas später behandelt.
1.4 Variablen eingesetzt...
Bislang hab ich nur aufgezählt, was es so für Datentypen gibt. Wie verknüpft man jetzt aber in der Programmiersprache die Variable mit dem Datentypen? Dies erfolgt indem man die Variable "deklariert" - sprich dem Compiler bekanntmacht, oder vorstellt.
Die Syntax dafür ist folgende:
Typname Variablenname;
Darüberhinaus kann man Variablen gleich auch bei der Deklaration initialisieren, d.h. mit einem Wert belegen:
Typname Variablenname = Wert;
Ein Beispiel:
|
Quellcode
|
1
2
3
4
5
|
//z.B. innerhalb der main-Methode wie in "HalloWelt.java"
int i;
double x = 2.718;
i = 15; //Dies ist eine Zuweisung
|
In den ersten beiden Zeilen wurden die Variablen i und x dem Compiler vorgestellt. i hat zunächst den Standardwert, nämlich 0 (könnte man z.B. sehen, indem man per System.out.println(i); diese Variable einfach mal ausgibt!). x wurde gleich ein Wert zugewiesen. Die Variable wurde also initialisiert. Danach wurde i ein konkreter Wert zugewiesen. Dies erfolgt mit dem einfach = Zeichen. Weitere Zuweisungen können an jeder Stelle vorgenommen werden - der jeweils aktuelle Wert der Variablen wird dabei einfach überschrieben.
1.5 Referenztypen
Bislang hatten wir nur die primitiven Datentypen. Darüberhinaus gibt es noch die Referenztypen, die da sind:
- Arrays
- Strings (Zeichenketten)
- (andere) Objekte (viel Spielraum für eigene Datentypen!)
Was genau ist eine Referenz? Nun - zu diesem Zeitpunkt auch noch relativ schwierig zu erklären, da immer noch die wesentlichen Grundlagen dazu fehlen. Ich bemüh mich aber mal

:
Bei den primitiven Datentypen werden alle Werte direkt in der Variablen an einer bestimmten Speicherstelle gespeichert. Wenn jetzt das Programm auf die Speicherstelle zugreift, wird der Wert direkt geändert.
Ein Referenztyp speichert seinen Wert nur indirekt auf dieser Speicherstelle. Man speichert auf dieser Speicherstelle also nur einen sogenannten Verweis (also ne Art Wegweiser) zu dem eigentlich gespeicherten Wert oder Objekt. Sinnbildlich kann man sich ein Parkplatz vorstellen. Man möchte ein Objekt nämlich Auto in einem Parkplatz (Speicherstelle) speichern (sprich parken). Das tut man irgendwo... an einer anderen Stelle speichert man das gleiche Auto erneut! Allerdings parkt man das Auto jetzt nicht um, sondern hinterlegt in diesem Parkplatz nen Schild - mein Auto befindet sich bei Nummer 314. In Java ist es sogar so, dass man Veränderung nur an diesem Schild (der Referenz) vornehmen kann. Z.B. wenn ich die Farbe des Autos ändern möchte, kann ich das an dem Schild machen, muss mir aber darüber klarwerden, dass ich nicht die Farbe des Schilds ändere, sondern die tatsächliche Farbe des Autos, was auf Platz 314 steht! Das heißt, mein Objekt existiert trotz mehrerer Parkplätze (Speicherstellen) tatsächlich nur ein einziges Mal. Alle Änderungen an den Referenzen ändern das Objekt ebenfalls direkt.
Dies muss man sich erst einmal klarmachen, dann wird man später auch eindeutig weniger Fehler machen
Referenzen werden immer mithilfe des new-Operators direkt erzeugt (es sei denn sie werden literal erzeugt, sie dafür 1.6 und 1.7). Man erstellt damit ein konkretes Objekt des angegebenen Typs.
Ein Beispiel wäre:
String s = new String();
Auch damit wird man jetzt noch nicht viel anfangen können - ich ahne, dass ich mich irgendwie wiederhole

- nicht verzweifeln. Ich hab das jetzt hier nur schonmal erwähnt, damit man sich später evtl. sinnig daran erinnert! Dann werde ich auch auf die im Script erwähnte Gleichheit von Referenzen eingehen...
1.6 Arrays
Oben hab ich's schon erwähnt - doch weniger erklärt, was das eigentlich ist. Nun offenbar ist ein Array ein Referenztyp und zudem sind Arrays auch Objekte. Aber was genau ist ein Array?
Ein Array ist eine Auflistung von bestimmten Elementen mit einem festen Datentyp. Die Größe der Arrays, also die Größe dieser Liste, kann zu Beginn also zur Deklarationszeit festgelegt werden, danach allerdings nicht mehr.
Mit dieser Liste könnte man also simple Formen von Adressdatenbanken erstellen.
Wie deklariert man Arrays?
Immer in zwei Schritten und zwar Deklaration und Initialisierung bzw. Erzeugung des Array-Objekts:
1.)
Datentyp[] Arrayname;
z.B.: int[] a;
2.)
Arrayname = new Datentyp[Größe_des_Arrays]
z.B.: a = new int[5];
Damit wird im Beispiel ein Array namens a deklariert und dann dem Namen ein konkret erzeugtes Array mit der Größe 5 hinzugefügt. Wichtig hierbei: Die Elemente werden nun von 0 bis 4 gezählt. Das Array wäre in diesem Fall also tatsächlich 5 Elemente groß.
Wie greift man jetzt aber auf die einzelnen Elemente des Arrays zu?
Ganz einfach - die Zuweisung von Werten z.B.:
Arrayname[index] = Wert;
Der index (selbst übrigens vom Typ int!) gibt den jeweiligen Speicherort an. Man kann sich das ganze dann als Tabelle vorstellen.
Im Beispiel könnte man alle Werte so zuweisen:
a[0] = 1;
a[1] = 3;
a[2] = 17;
a[3] = 9;
a[4] = 7;
als Tabelle:
Index | Wert
0| 1
1| 3
2| 17
3| 9
4| 7
Sollte eigentlich kein Problem sein, oder? Wichtig jedoch ist, dass jedes Array tatsächlich nur einen Datentyp besitzt. Man kann also nicht Integerwerte und Zeichen gleichzeitig in dieser "Tabelle" unterbringen.
Deklaration und Zuweisung kann auch vereinfacht in einem Rutsch passieren, z.B.:
int[] a = new int[5];
und es gibt sogar nen Literal für die ganze Angelegenheit:
int[] a = {1,3,17,9,7};
würde das gleiche Array wie durch die Zuweisung oben definieren... wenn man konkrete Werte zuordnen will von Anfang an, also die schickeste Methode Arrays zu erstellen.
Wenn man jetzt übrigens auf ein Arrayelement zugreifen möchte, was nicht existiert, gibt die VM eine Exception zurück (ArrayIndexOutOfBoundsException), dass der angegebene Index außerhalb der Reichweite des Arrays liegt. Wie etwa in unserem Beispiel:
a[10] = 12;
eine solche Fehlermeldung hervorbringen würde...
Man kann natürlich nicht nur schreiben, sondern einfach lesen und z.B. in eine andere Variable zurückschreiben:
|
Quellcode
|
1
2
3
4
5
|
//innerhalb einer main-Methode
int x;
int[] a = {1,3,17,9,7};
x = a[3];
System.out.println(x); //was wird jetzt ausgegeben??? man fängt mit 0 an zu zählen!!!
|
Jetzt gibts aber noch was extrem lustiges, nämlich
mehrdimensionale Arrays (oder auch Arrays von Arrays).
Eine Deklaration wäre z.B.:
int[][] a = new int[2][3];
und die folgende Zuweisung z.B.:
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 7;
a[1][0] = 19;
usw...
Man erkennt, dass die Speicherstelle 0 des Arrays a genau drei Speicherstellen für konkrete Integerwerte zur Verfügung stellt. Die nächste und letzte Speicherstelle 1 ebenfalls wieder 3...
Damit kann man sich schon eine komplexere Kundendatenbank vorstellen, in denen Namen, Vornamen, Telefonnummern etc. gespeichert werden könnten!
Man kann solche Arrays natürlich auch wieder literal erzeugen:
int[][] a = { {1,2,7}, {19,12,13} };
Das würde in etwa dem oberen Schema entsprechen. Aber man kann tatsächlich auch folgende nicht so gleichmäßige Muster erzeugen:
int[][] a = { {0}, {1, 3, 4}, {1,5,3,99,3,1}, {2}};
Hiermit wird ein Array a erzeugt, dass aus 4 Elementen besteht, die selbst wieder Arrays sind. Das erste Element hat die Größe 1, das zweite 3, das dritte 6 und das letzte wieder 1. Zugegriffen wird ganz logisch z.B. auf die 99 des dritten Elements so:
a[3][4]; //Das dritte Element und von diesem Array das 4. Element...
Kleiner Hinweis noch am Rande. Ich hatte ja schon erwähnt, dass Arrays Objekte sind. Ohne große Erklärungen betreiben zu müssen - die Arrays besitzen damit Methoden und auch Attribute. Ein ganz sinnvolles Attribut ist natürlich die Größe des Arrays, dass man mittels
Arrayname.length ermittelt werden kann.
|
Quellcode
|
1
2
3
4
5
6
7
8
9
10
|
public class Arraytest {
public static void main (String[] args) {
int[] a = {1,3,17,9,7};
int[][] b = { {0}, {1, 3, 4}, {1,5,3,99,3,1}, {2}};
System.out.println(a.length); //Größe von Array a
System.out.println(b[2].length); //Größe des dritten Arrays von Array b!
}
}
|
Es wird natürlich später noch jede Menge Beispiele zu Arrays geben - hier sei mir erlaubt nicht weiter darauf einzugehen, da ja noch wesentliche Sprachkentnisse fehlen, damit man überhaupt solche Beispiele versteht.
1.7 Strings
Jetzt endlich will ich auf die Zeichenketten eingehen. Diese kann man auch als Aneinanderreihung von Zeichen (also char's) verstehen und nehmen eine gewisse Sonderrolle gegenüber den primitiven Datentypen ein. Man benutzt sie fast wie primitive Datentypen, sollte aber nicht vergessen, dass man hier einen Referenztypen hat, sprich mit nem Objekt hantiert... das wird später noch deutlich wiederholt werden...
Das Literal zum String haben wir schon mehrfach benutzt - es ist das doppelte Anführungszeichen, also z.B. "abc" oder "Hallo Welt!".
Man deklariert wie gewohnt:
String s = "abc";
oder natürlich auch
String s;
s = "abc";
Man erkennt schon an der Deklaration des Strings einen deutlichen Unterschied! String - also der Datentyp - wird auf einmal groß geschrieben! Das kommt einfach daher, dass es halt tatsächlich eine eigene Klasse String gibt. Mit dem Literal "abc", was man dem String s zuweist, wird also ein konkretes Objekt des Typs String erzeugt. Die Klasse String selbst hat furchtbar viele Methoden mit denen man Strings manipulieren, durchsuchen, etc... kann.
Diese Methoden möchte ich aber zu einem späteren Zeitpunkt vorstellen... da hat man jetzt imho noch nichts von.
Aber an dieser Stelle erkennt man schon mehr von dem Beispiel-Programm "HalloWelt.java". Die Methode System.out.println() gibt ganz offenbar einen String, also eine Zeichenkette aus. Man könnte das Ganze also auch so schreiben:
|
Quellcode
|
1
2
3
4
|
//nur die entsprechende Stelle in der main-Methode verändert!
String s = "Hallo Welt!";
System.out.println(s);
|
ohne das Ergebnis zu verändern
Konkatenation von Strings
Die Konkatenation oder Verkettung von Strings ist eine Sache die man natürlich wissen sollte. Oft muss man bestimmte Zeichenketten miteinander verbinden, weil bestimmte Daten aus mehreren verschiedenen Variablen in einer entsprechenden Ausgabe zusammengefügt werden sollen.
Die Verkettung zweier Strings erfolgt mithilfe des "+"-Zeichens und den entsprechenden Anführungszeichen der Strings oder der Variablen selbst.
Also beispielsweise:
"Hallo"+" Zeichenkette!"
würde die beiden String-Literale "Hallo" und " Zeichenkette!" miteinander verbinden.
Ein praktischeres Beispiel:
|
Quellcode
|
1
2
3
4
|
//wieder in einer main-Methode
String s1 = "Hallo";
String s2 = "Welt!";
System.out.println(s1+s2);
|
Die beiden Strings in den Variablen s1 und s2 werden einfach per + miteinander verknüpft. Doch offenbar gibt es, wenn man das ganze denn jetzt mal testweise ausführt, nen kleinen Schönheitsfehler. Die Ausgabe würde jetzt lauten "HalloWelt!". Nun man kann selbstverständlich auch String-Literale mit Variablen mixen:
|
Quellcode
|
1
2
3
4
|
//wieder in einer main-Methode
String s1 = "Hallo";
String s2 = "Welt!";
System.out.println(s1+" "+s2);
|
Jetzt kommt die schon bekannte Ausgabe mit korrektem Leerzeichen daher. Das Verknüpfungszeichen "+" ist übrigens äquivalent zum Verknüpfungszeichen "." in PHP (dieser Einschub sei in einem Webstyleboard erlaubt

).
Interessant ist noch, dass auch Variablen anderen Datentyps mithilfe eines String-Literals zu einer Zeichenkette umgewandelt werden kann.
|
Quellcode
|
1
2
3
|
//wieder in einer main-Methode
int zahl = 17;
System.out.println("Die gesuchte Zahl ist: "+zahl);
|
Hier macht der Compiler das Umwandeln des Datentyps offenbar automatisch. Sonst ist diese Aktion nicht selbstverständlich. Es hagelt gerne Fehlermeldungen, wenn man an einer Stelle einen falschen Datentyp benutzt... dies ist sicherlich ebenfalls für einen PHP-Programmierer neu

- dort wandelt der Interpreter den Datentyp immer selbstständig um.
[to be continued]