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?
Author: overexchange, 2015-06-11

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 en int en arrondissant vers zéro. Ensuite, le int 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.

 17
Author: dhke, 2015-06-11 09:44:05