Règles de casting pour les types primitifs en java
En java,
Il y a des types intégraux(char
/short
/int
/long
/byte
)
Il existe des types flottants(float
/double
)
Il existe un type booléen(boolean
), pas un type intégral, contrairement au langage C.
Question 1)
Existe-t-il une règle générique pour le casting(selon JLS) qui parle, quel type peut être converti en un autre type? Par bon sens, je sais que, les types intégraux et flottants en boolean
ne sont pas autorisés
Question 2)
Veuillez m'aider à comprendre les raisons de la sortie ci-dessous:
/*
* Casting rules for primitive types
*/
double aDoubleValue = 30000000000000000000.123438934;
int doubleToInt = (int)aDoubleValue; //stores max value 2147483647, makes sense!!
byte doubleToByte = (byte)aDoubleValue; //stores -1, why not 127?
short doubleToShort = (short)aDoubleValue; // stores -1, why not 32767?
long doubleToLong = (long)aDoubleValue; // stores 9223372036854775807, makes sense!!
float doubleToFloat = (float)aDoubleValue; // stores 3.0E19, 3.0 x 10^19 max value of float
char doubleToChar = (char)aDoubleValue; // what does this store?
1 answers
JL listes
19 les conversions spécifiques sur les types primitifs sont appelées les conversions primitives élargies:
- octet à court, int, long, float, ou double
- court à int, long, float, ou double
- char à int, long, float, ou double
- int à long, float, ou double
- long à flotter ou double
- flotter pour doubler
Tout le reste a besoin d'un casting explicite. Rétrécissement, est un peu plus complexe:
-
double
àfloat
utilise l'arrondi standard IEEE 754. - les valeurs entières ont leurs bits les plus significatifs réduits à la largeur disponible du type cible. Cela peut entraîner l'apparition d'un bit de signe, par exemple
(byte)0xfff == (byte)-1
; - Si le type source est à virgule flottante et le type cible est
long
, la valeur est convertie en arrondissant vers zéro. - Si le type source est à virgule flottante et que le type cible est intégral mais pas
long
, la valeur est d'abord convertie enint
en arrondissant vers zéro. Ensuite, leint
résultant est converti en type cible en utilisant la conversion entière.
Exemples:
int doubleToInt = (int)aDoubleValue;
Rendements Integer.MAX_VALUE
selon les règles d'arrondi.
byte doubleToByte = (byte)aDoubleValue;
Convertit d'abord en int
, donnant Integer.MAX_VALUE
, puis convertit cela en byte
. Integer.MAX_VALUE
est 0x7fffffff
, d'où la valeur de l'octet 0xff
, qui est -1
.
short doubleToShort = (short)aDoubleValue;
Encore une fois: convertit en int
, donnant Integer.MAX_VALUE
. 0x7fffffff
à short
rendements 0xffff
, c'est à dire -1
.
La chose délicate est en fait la conversion en-char
. char
est un seul caractère unicode de 16 bits, donc char doubleToChar = (char)aDoubleValue
vous donne '\uffff'
selon les règles maintenant familières.
Comme on peut le voir, il existe une différence entre les opérations de rétrécissement en virgule flottante et en entier. Les opérations à virgule flottante effectuent un arrondi réel, tandis que les opérations entières effectuent un serrage au niveau du bit.
La sémantique entière est probablement héritée de C. Au moins la première étape de la les ops de rétrécissement float-to-integral sont également ce que vous attendiez. Les deuxièmes étapes de rétrécissement, de double / float à court, octet et char peuvent sembler un peu surprenantes, mais si vous lancez vraiment float à court, vous devriez probablement vérifier que vous savez ce que vous faites de toute façon.