2.2.3 Typkonversion bei Zuweisung verschiedener Typen

Die Sprache Java und ihre (Lautzeitumgebung) sind typsicher. Typsicher bedeutet, dass bei Zuweisungen für Variablen der Typ der Variable und der zugewiesene Typ eines Wertes geprüft werden und nur sichere Zuweisungen erlaubt werden. Der Übersetzer (javac) erkennt dies schon beim Parsen (lesen) des Quellcodes und meldet dies als Fehler.

Beispiel: Der Wertebereich einer Variable vom Type short endet bei 65535. Der Typ int hat jedoch einen Wertebereich der bis 4294967295 reicht. Im folgenden Fall kann es also zu einem Überlauf kommen:

short a;
int b;
....
a = b;

Der Übersetzer wird einen Fehler melden, da es hier zu einem Überlauf/Unterlauf aufgrund der unterschiedlichen Wertebereiche kommen kann.

Die Zuweisungskompatibilität kann man als Teilmengen mit dem Symbol ⊃ darstellen. In Java gilt die folgenden Beziehung:

doublefloatlongintshort/char byte

  • Alle Zuweisungen von bytedouble sind erlaubt. Java führt hier eine implizite Konvertierung (impliziter Cast) durch, weil es eine sichere Operation ist.
  • Alle Zuweisung von double ➔ byte werden vom Übersetzer nicht akzeptiert.

Bei Berechnungen vor der Zuweisung kommen eventuell verschieden Typen in Operationen (z.Bsp.) Addition vor.

Hier verfährt Java nach der folgenden Regel:

  • Der jeweils kleinere Operandentyp wird vor der Operation in den größeren konvertiert.
  • Die Operanden werden jedoch zumindest in den Typ int konvertiert
  • Das Ergebnis hat den gleichen Typ wie die beiden Operanden (nach Konvertierung)

Explizite Typkonvertierungen(Casts)

Um Zuweisungen zwischen inkompatiblen Typen zu erzwingen kann man den Zieltyp in runden Klammern dem Ausdruck voran stellen. Diesen Operator nennt man Castoperator (cast im englischen: gießen, betonieren).

Beispiel

short a;
int b;
....
a = (short)b; 

Hiermit erzwingt man Operationen die unsicher sein können! Es kann zu Überläufen in Wertebereichen oder Präzisionsverlusten kommen kann. Der Entwickler übernimmt hier die Verantwortung und überstimmt den Übersetzer. Der Castoperator sollte daher nur wenn nötig eingesetzt werden.

Das Applet zur Rechten ist in der Lage einen beliebigen Ganzzahltypen auf einen beliebigen anderen Ganzzahltypen zu zuweisen.

Die Variable y enthält den Eingabewert. Den Typ von y kann man in der rechten Spalte wählen.

Der Wert von y wird mit Hilfe einer Typkonversion (Cast) auf x zugewiesen. Den Typ von x kann man links wählen.

Nach der Wahl der Typen und des Eingabewerts kann die Zuweisung mit dem "Enter" Button gestartet werden.

Fragen:

  • Was geschieht bei der Typkonversion mit negativen Werten (siehe rotes Vorzeichenbit)?
  • Was geschieht bei der Zuweisung von großen Typen auf kleine Typen? Was geschieht mit den Vorzeichen?
  • Was geschieht wenn Zeichen (Typ char) auf andere Typen zugewiesen werden?

Zum Testen bitte runterladen: BinaerCastApplet.jar

Starten Sie die Anwendung mit einem Doppelclick im Download Ordner oder öffen ein Terminal und führen den folgenden Befehl im Download Ordner aus:

java -jar BinaerCastApplet.jar

Es sollte ein Fenster erscheinen welches wie folgt aussieht: 

Screenshot BinearCastApplet

 

Quellcode des Applets und Anleitung zum Starten als Javaprogramm von der Konsole

Anonymous (not verified)

Sun, 12/16/2012 - 13:33

Laut "double ⊃ float ⊃ long ⊃int ⊃ short/char ⊃ byte" ist die Zuweisungen von Long-Literalen auf eine Float-Variable vom Compiler akzeptiert. Aber kommt es hier nicht zu Genauigkeitsverlusten, da long 64 Bit Genauigkeit hat und float nur 32 Bit. Und wenn ja, wieso akzeptiert der Compiler das dann trotzdem?

Korrekte Beobachtung. Ein long Typ kann Werte noch ohne Rundungsfehler korrekt darstellen wo ein float Typ schon im Bereich >1 also 20, 21, 22 etc.

Das ganze ist (wahrscheinlich) erlaubt da

  1. das Zahlenintervall des Typs float größer als das des Typ long ist. Es gibt also keinen Überlauf an den Grenzen der Zahlenintervalle
  2. Wer mit dem Typ float arbeitet muss wissen, das hier immer gerundet werden kann.

Anonymous (not verified)

Sun, 12/16/2012 - 13:41

Wenn ich in dem Applett auf der linken Seite den Typ byte wähle und auf der rechten Seite den Typ int. Dann müsste doch oben eigentlich in blauer Schrift die Zuweisung "byte x=(byte) y" stehen, oder? Jedenfalls steht dort "byte x=(int) y"; das würde doch gar nicht funktionieren, denn dann würde ich ja immer noch ein Int-Literal einer Byte-Variablen zuweisen.