Primitive Datentypen


Nichts gegen meinen Datenbank-Admin!

Nein, der ist nicht gemeint. Primitiv ist ein Datentyp in Java wenn der Wert den dieser Datentyp speichert direkt in seinem Speicherbereich liegt. Referenzielle Datentypen speichern im Gegensatz dazu in ihrem Speicherplatz nur eine Referenz auf den Speicherplatz eines Objektes, aber um diese kümmern wir uns jetzt noch nicht.

In Java gibt es zwei bis drei Arten von primitiven Datentypen, numerische, character und boolean (der Warheitswert). Warum zwei bis drei? Numerische- und Character-Datentypen sind nicht so unterschiedlich wie man vielleicht vermuten würde.

Wahrheitswert

Es gibt einen Wahrheitswert-Datentyp, boolean, dieser kann einen von zwei Werte speichern, true oder false, kein 0 oder 1, und auch nicht wahr oder falsch, sondern nur true oder false.

boolean wahrheit = true;

Zeichen

Der Zeichen-Datentyp character kann ein Zeichen speichern, dieses kann entweder direkt angegeben werden oder als Unicode-Nummer und sogar als Ganzzahl. Der Wertebereich geht von 0 bis 65535. Uns steht also das ganze Unicode-Alphabet zur Verfügung, allerdings dürfen wir nur ein Zeichen benutzen.

public class MeinA {
 public static void main(String[] args) {
 char zeichen = 'a';
 System.out.println(zeichen);
 zeichen = '\u0061';
 System.out.println(zeichen);
 zeichen = 97;
 System.out.println(zeichen);
 }
}

Kompilieren, ausprobieren, staunen. Woran liegt denn dieses Ergebnis? 61 in Hexadezimal entspricht 97 im dezimalen Zahlensystem und das auf dieser Position das ‚a‘ liegt am ASCII-Code von 1960, denn dieser bildet den Anfangsteil von Unicode.

Bei der Zuweisung immer daran denken einfache Hochkommata zu verwenden, keine „Gänsefüßchen“. Und bei der dezimalen Zahl werden keine Hochkommata verwendet, javac kontert solche Versuche mit einem Kompilierfehler.

Zahlenwerte

Zahlenwerte zu speichern wäre auch noch ganz nett. Und dafür gibt es in Java mannigfaltige Möglichkeiten!

Es wird unterschieden zwischen Ganzzahlenwerten und Fließkommazahlen.

Zu den Ganzzahlenwerten gehören byte, short, int und long, diese unterscheiden sich nur in ihrem Wertebereich und Speicherbedarf.

Zu dem Fließkommazahlen gehören float und double, diese unterscheiden sich in ihrer Genauigkeit und Speicherbedarf.

Was mit höherer Genauigkeit gemeint ist zeigt das folgende Programm:

import static java.lang.Math.PI;
public class Fliesskomma {
    public static void main(String[] args) {
        float geringeGenauigkeit = (float)PI;
        System.out.println("float:  " + geringeGenauigkeit);
        double hoheGenauigkeit = PI;
        System.out.println("double: " + hoheGenauigkeit);
    }
}

Was hier auch noch auffällt ist etwas anders mit dem wir uns beschäftigen müssen, wenn wir mit Datentypen umgehen, die statische Typisierung und das Casting.

Eine nicht-typisierte Variable würde alle möglichen Werte aufnehmen können, mal einen Ganzzahlenwert und eine Zeile weiter einen Fließkommazahlenwert, so funktioniert das in Java nicht. Ein int wird immer ein int bleiben, ein float immer ein float, der Typ der Variable bleibt also statisch.

Trotzdem haben wir den Wert von PI in unterschiedlicher Genauigkeit in ein float und einen double bekommen, wie geht das?

Diese durchaus mit Verlust behaftete Umwandlung geben wir explizit an, durch einen cast. Dies bedeutet nichts anderes als das wir den Zieldatentyp in Klammern vor die Datenquelle anderen Typs schreiben: „(float)PI“.

Worauf bei float noch zu achten ist, ist dass Fließkommazahlen in Java per default double-Werte sind. Eine „1.0“ ist also ein double-Wert,  wenn dieser in ein float geschrieben werden soll muss ein f oder F an den Zahlenwert angehängt werden, alternativ geht natürlich auch ein cast. Schreibt man aber nur „float f3 = 1.0;“, dann wird es zu einem Kompilierfehler kommen.

public class ZahlMitF {
    public static void main(String[] args) {
        float f1 = 1.0f;
        float f2 = (float)1.0;
        System.out.println(f1);
        System.out.println(f2);
    }
}

Implizierte Typumwandlungen, also ohne Angabe von cast funktionieren in Java auch, aber nur wenn kein Wertverlust droht. Also ein byte kann ohne cast in ein int geschrieben werden.

public class Byte2Int {
 public static void main(String[] args) {
 byte b = 5;
 int i = b;
 System.out.println(i);
 }
}

Der drohende Wertverlust ist hier definiert über den Datentyp, nicht über den Wert. Daher muss ein double mit dem Wert „1.0“ per cast in einen float gewandelt werden.

Es gibt aber nicht nur größere oder kleinere Wertebereiche sondern auch verschobene bei denen ein cast notwendig ist, ein solcher Fall sind Zahlenwerte die in char gewandelt werden sollen.

class Zahl2Char{
    public static void main(String[] args){
        byte b = 97;
        short s = 97;
        int i = 97;
        long l = 97;
        char c1 = (char)b;
        char c2 = (char)s;
        char c3 = (char)i;
        char c4 = (char)l;
        System.out.println(c1 + " " + c2 + " " + c3 + " " + c4);
    }
}

Denn man könnte davon ausgehen, dass z.B. byte in char implizit gewandelt werden könnte, da der Wertebereich von byte kleiner ist als der von char. Allerdings beginnt der Wertebereich von byte im negativen Bereich und der Wertebereich von char mit der 0 in den positiven Bereich hinein.

Probiert man den Fall, char in nummerische Datentypen zu wandeln, müssen nur byte und short mit einem cast versehen werden, da der Wertebereich eines char problemlos in den Wertebereich eines int oder long passt.

class Char2Zahl{
    public static void main(String[] args){
        char c1 = 'a';
        char c2 = 'a';
        char c3 = 'a';
        char c4 = 'a';
        byte b = (byte)c1;
        short s = (short)c2;
        int i = c3;
        long l = c4;
        System.out.println(b + " " + s + " " + i + " " + l);
    }
}

Es ist wichtig diesen Zusammenhang zu verstehen, damit man sich nicht wundert, dass man jetzt casten muss, obwohl es bei dem anderen numerischen Datentyp vorher es nicht notwendig war.

Datentypvonbis
booleantruefalse
char065.535
byte-128127
short-32.76832.767
int-2.147.483.6482.147.483.647
long-9.223.372.036.854.775.8089.223.372.036.854.775.807
float1,40239846E-453,40282347E+38
double4,94065645841246544E-3241,79769131486231570E+308

 

Kommentar erstellen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.