1. Typisierung
Variablen primitiver Typen (mit Ausnahme des boolean
Typs) werden zum Speichern verschiedener Arten von Zahlen verwendet. Obwohl sich die Variablentypen nie geändert haben, gibt es einen Ort, an dem Sie von einem Typ in einen anderen konvertieren können. Und dieser Ort ist Aufgabe .
Variablen unterschiedlichen Typs können einander zugeordnet werden. Dabei wird der Wert einer Variablen eines Typs in einen Wert eines anderen Typs umgewandelt und der zweiten Variablen zugewiesen. In diesem Zusammenhang können wir zwei Arten der Typkonvertierung unterscheiden: Erweiterung und Verengung.
Eine Erweiterung ist wie das Verschieben eines Wertes von einem kleinen Korb in einen großen: Dieser Vorgang verläuft nahtlos und schmerzlos. Eine Verengung entsteht, wenn Sie einen Wert von einem großen Korb in einen kleinen verschieben: Möglicherweise ist nicht genügend Platz vorhanden und Sie müssen etwas wegwerfen.
Hier sind die Typen, sortiert nach Korbgröße:
2. Erweiterungstypkonvertierungen
Oft ist es notwendig, eine Variable eines numerischen Typs einer Variablen eines anderen numerischen Typs zuzuweisen. Wie machst du das?
Java hat 4 Ganzzahltypen:
Typ | Größe |
---|---|
byte |
1 byte |
short |
2 bytes |
int |
4 bytes |
long |
8 bytes |
Variablen, die in kleineren Körben gespeichert sind, können immer Variablen zugewiesen werden, die in größeren Körben gespeichert sind.
int
, short
und byte
Variablen können einfach Variablen zugewiesen werden long
. short
und byte
Variablen können Variablen zugewiesen werden int
. Und byte
Variablen können Variablen zugewiesen werden short
.
Beispiele:
Code | Beschreibung |
---|---|
|
Dieser Code lässt sich problemlos kompilieren. |
Eine solche Konvertierung von einem kleineren zu einem größeren Typ wird als Erweiterungstypkonvertierung bezeichnet .
Was ist mit reellen Zahlen?
Bei ihnen ist alles beim Alten – auf die Größe kommt es an:
Typ | Größe |
---|---|
float |
4 bytes |
double |
8 bytes |
float
double
Variablen können problemlos Variablen zugewiesen werden . Interessanter sieht es jedoch bei den Integer-Typen aus.
Sie können einer Variablen eine beliebige Ganzzahlvariable zuweisen float
. Sogar der long
Typ, der 8 Byte lang ist. Und Sie können float
einer Variablen alles zuweisen, was Sie wollen – jede ganzzahlige Variable oder Variable double
:
Code | Notiz |
---|---|
|
|
Beachten Sie, dass die Konvertierung in einen echten Typ zu einem Genauigkeitsverlust führen kann, da nicht genügend signifikante Ziffern vorhanden sind.
Bei der Konvertierung von Ganzzahlen in Gleitkommazahlen können die niederwertigen Zahlenteile verworfen werden. Da aber unter Bruchzahlen Näherungswerte gespeichert werden, sind solche Zuweisungsoperationen zulässig.
3. Einschränkende Typkonvertierungen
Wie sieht es mit den anderen Möglichkeiten aus? long
Was ist, wenn Sie einer Variablen einen Wert zuweisen müssen int
?
Stellen Sie sich eine Variable als Korb vor. Wir haben Körbe in verschiedenen Größen: 1, 2, 4 und 8 Byte. Es ist kein Problem, Äpfel von einem kleineren Korb in einen größeren umzuladen. Beim Umstellen von einem größeren Korb in einen kleineren können jedoch einige Äpfel verloren gehen.
Diese Transformation – von einem größeren Typ zu einem kleineren Typ – wird als einschränkende Typkonvertierung bezeichnet . Bei der Durchführung einer solchen Zuweisungsoperation kann es sein, dass ein Teil einer Zahl einfach nicht in die neue Variable passt und daher verworfen wird.
Wenn wir einen Typ eingrenzen, müssen wir dem Compiler ausdrücklich mitteilen, dass wir keinen Fehler machen und absichtlich einen Teil der Zahl verwerfen. Hierzu wird der Typecast-Operator verwendet. Es handelt sich um einen Typnamen in Klammern .
In solchen Situationen verlangt der Java-Compiler , dass der Programmierer den Typecast-Operator angibt. Im Allgemeinen sieht es so aus:
(type) expression
Beispiele:
Code | Beschreibung |
---|---|
|
Der Typecast-Operator muss jeweils explizit angegeben werden |
Hier a
ist gleich 1
, und vielleicht scheint der Typecast-Operator übertrieben zu sein. Aber was wäre, wenn a
sie größer wären?
Code | Beschreibung |
---|---|
|
|
Eine Million passt perfekt in ein long
und in ein int
. Wenn einer short
Variablen jedoch eine Million zugewiesen wird, werden die ersten beiden Bytes verworfen und nur die letzten beiden Bytes bleiben erhalten. Und bei der Zuweisung zu a byte
bleibt nur das letzte Byte übrig.
So sind die Zahlen im Speicher angeordnet:
Typ | Binäre Notation | Dezimalschreibweise |
---|---|---|
int |
0b 00000000 00001111 01000010 01000000 | 1000000 |
short |
0b 01000010 01000000 | 16.960 |
byte |
0b 01000000 | 64 |
char
Typ
A char
belegt wie a short
zwei Bytes, aber um eines in ein anderes umzuwandeln, müssen Sie immer einen Typumwandlungsoperator verwenden. Das Problem hierbei ist, dass der Typ signiert ist und Werte von bis short
enthalten kann , der Typ jedoch ohne Vorzeichen ist und Werte von bis enthalten kann .-32,768
+32,767
char
0
65,535
Negative Zahlen können nicht in einer gespeichert werden char
, sie können jedoch in einer gespeichert werden short
. Und a short
kann keine Zahlen speichern, die größer als sind 32,767
, aber solche Zahlen können in a gespeichert werden char
.
4. Art eines Ausdrucks
Was passiert, wenn Variablen unterschiedlichen Typs im selben Ausdruck verwendet werden? Logischerweise verstehen wir, dass sie zunächst in einen gemeinsamen Typ konvertiert werden müssen. Aber welcher?
Natürlich zum größeren.
Java konvertiert immer in den größeren Typ. Grob gesagt wird zunächst einer der Typen erweitert und erst dann wird die Operation mit Werten desselben Typs ausgeführt.
Wenn an int
und a an einem Ausdruck beteiligt sind, wird long
der Wert von in a konvertiert und erst dann wird die Operation fortgesetzt:int
long
Code | Beschreibung |
---|---|
|
a wird zu a erweitert long und dann erfolgt die Addition. |
Gleitkommazahlen
Wenn in einem Ausdruck eine Ganzzahl und eine Gleitkommazahl ( float
oder double
) beteiligt sind, wird die Ganzzahl in eine Gleitkommazahl ( float
oder double
) umgewandelt und erst dann wird die Operation ausgeführt.
Wenn die Operation a float
und a umfasst, wird double
das in a konvertiert . Was eigentlich erwartet wird.float
double
Die Typen byte
, short
und char
werden immer in konvertiert, int
wenn sie miteinander interagieren. Es gibt einen guten Grund, warum der int
Typ als Standard-Integer-Typ gilt.
Wenn man a byte
mit a multipliziert short
, erhält man ein int
. Wenn man a byte
mit a multipliziert byte
, erhält man ein int
. Auch wenn man a byte
und a hinzufügt byte
, erhält man ein int
.
Dafür gibt es mehrere Gründe. Beispiele:
Code | Beschreibung |
---|---|
|
110 * 120 ist 13,200 , was etwas größer als der Maximalwert des byte Typs ist:127 |
|
110 + 120 ist 230 , was ebenfalls etwas größer als der Maximalwert des byte Typs ist:127 |
Wenn wir eine 8-Bit-Zahl (1 Byte) mit einer 8-Bit-Zahl (1 Byte) multiplizieren, erhalten wir im Allgemeinen eine Zahl, die 16 Bits (2 Bytes) belegt.
Dadurch werden alle Operationen mit Integer-Typen kleiner als int
immer sofort in s konvertiert int
. int
Und das bedeutet, dass Sie den Typumwandlungsoperator immer explizit angeben müssen, wenn Sie das Ergebnis der Berechnung in einer Variablen eines Typs speichern möchten, der kleiner als ist .
Beispiele:
Code | Beschreibung |
---|---|
|
Der byte * byte Ausdruck wird ein seinint |
|
Der byte + byte Ausdruck wird ein seinint |
|
Der byte + int Ausdruck wird ein sein. int Der wörtliche Ausdruck ist ein int . |
5. Eine wichtige Nuance
Der Typecast-Operator hat eine ziemlich hohe Priorität.
Das heißt, wenn ein Ausdruck beispielsweise eine Addition und einen Typecast-Operator enthält, wird die Typecast vor der Addition durchgeführt.
Beispiel:
Code | Beschreibung |
---|---|
|
Der Typecast-Operator wird nur auf die Variable angewendet a , die bereits eine ist byte . Dieser Code lässt sich nicht kompilieren. |
|
Das ist der richtige Weg. |
Wenn Sie den gesamten Ausdruck in einen bestimmten Typ konvertieren möchten und nicht nur eine Komponente des Ausdrucks, schließen Sie den gesamten Ausdruck in Klammern ein und setzen Sie den Typumwandlungsoperator voran.