web-dev-qa-db-fra.com

Pourquoi l'octet ne prend-il pas 0xff en java?

Pourquoi le compilateur Java ne me laissera-t-il pas mettre 0xff dans un byte, 0xff est de 8 bits, ce qui correspond à la taille du type de données byte.

Quelqu'un peut-il expliquer pourquoi 1 fonctionne et pourquoi 2 ne fonctionne pas?

class a
{
        public static void main(String[] args)
        {
                // 1 :: results in error
                byte a = 0xff;          
                System.out.printf("%x\n",a);

                //2 :: works fine
                byte a = (int)0xff              
                System.out.printf("%x\n",a);
        }
}

EDIT J'ai lu la réponse affirmant que 0xff est 255, comment? N'est-ce pas 1111 1111, Ce qui fait 0xff, -128 ou 255 ou quoi que ce soit d'ailleurs. Pourquoi ne le traitera-t-il pas simplement comme 1111 1111 et non les 8 bits de cet octet à 1.

28
vikkyhacks

Le type Java byte est un type intégral signé 8 bits avec des valeurs dans la plage -128 à +127. Le littéral 0xff représente +255 qui est en dehors de cette plage.

Dans le premier exemple, vous essayez d'affecter une valeur hors plage à un byte. C'est une erreur de compilation.

Dans le deuxième exemple, le (byte) cast effectue une conversion de rétrécissement explicite, qui supprime les bits de poids fort du littéral entier ... vous donnant la valeur -127 dans votre variable byte.


En fait, la situation avec le premier exemple est un peu plus compliquée que cela. Considère ceci:

byte a = 1;         // OK
int i = 1;
byte b = i;         // Compilation error
byte c = (byte) i;  // OK

Dans des circonstances normales, vous ne pouvez pas affecter un int à un byte sans transtypage. Toutefois, si la valeur affectée est un littéral et que la valeur littérale se situe dans la plage du type cible, le Java autorise l'affectation sans a jeter. La valeur du littéral est implicitement réduite de int à byte.

Ceci est décrit dans JLS §5.2 qui définit les conversions qui peuvent être effectuées dans une affectation:

"Une conversion primitive de rétrécissement peut être utilisée si le type de la variable est octet, court ou caractère, et que la valeur de l'expression constante est représentable dans le type de la variable."

Et comme vous pouvez le voir, cela ne s'applique pas juste aux littéraux. Il s'applique à toutes les expressions constantes (au moment de la compilation)!


SUIVI

J'ai lu la réponse en affirmant que 0xff est 255, comment? N'est-ce pas 1111 1111, Ce qui rend 0xff, -128 ou 255 ou quoi que ce soit d'ailleurs?

Le littéral 0xff est un littéral entier de type int. La valeur int du littéral 0xff est en fait 0000 0000 0000 0000 0000 0000 1111 1111 en binaire ou +255 en décimal. En revanche, le littéral -1 a le modèle de bits 1111 1111 1111 1111 1111 1111 1111 1111.

Pourquoi ne le traitera-t-il pas simplement comme 1111 1111 et non les 8 bits de cet octet à 1?

Car 0xff est un littéral entier de type int. Ce n'est pas un littéral 8 bits, car les littéraux 8 bits n'existent pas en Java. Comme JLS §3.10.1 dit:

"Un littéral entier est de type long s'il est suffixé avec une ASCII lettre L ou l (ell) ; sinon il est de type int ( §4.2.1 ). "

51
Stephen C

0xff est un représentation hexadécimale d'un nombre. En d'autres termes, le nombre est la base 16.

f = 15 en hex.

La valeur est égale à

15 * 16^1 + 15 * 16^0 = 255

Il s'agit d'un littéral entier (utilise 4 octets), qui dépasse la plage de valeurs de byte.

Aucun des deux exemples que vous avez publiés ne se compilera car aucun ne rentre dans la plage de valeurs de byte de -128 to 127. Vous pouvez lire sur les plages de valeurs de type primitif ici .

Cela fonctionnera

byte a = (byte)0xff; 
System.out.println(a);

et imprimer -1, car un octet réduit la conversion de 255 est -1.

15

Tout d'abord, si j'essaie d'exécuter votre code, le cas ne fonctionne pas non plus. Vous convertissez 0xff au type de données primitif int (qui a 32 bits) et souhaitez le stocker dans un "octet" avec seulement 8 bits. Java traite également votre premier cas comme int, ce qui entraîne le même problème.

Étant donné que le type Java 'byte' est un entier signé de 8 bits (de -128 à 127), pour afficher/imprimer l'octet en hexadécimal, vous pouvez utiliser Integer.toHexString ('le octet primitif '& 0xFF) où' & 0xFF 'est un masque de bits pour tenir compte du fait qu'Integer utilise un entier 32 bits et que l'octet utilise 8 bits.

    byte myByte = (byte)0xff;
    System.out.println(Integer.toHexString(myByte & 0xFF));

Cela produit:

ff
4
Philipp Seeger

0xff est 255. Bien que cela tienne dans un entier 8 bits non signé, byte est signé (-128 à 127). Le rétrécissement enlèvera les bits hauts et s'adaptera à 8 en 8 sans tenir compte du signe.

4
Andrey Akhmetov