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.
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
est255
, comment? N'est-ce pas1111 1111
, Ce qui rend0xff
,-128
ou255
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 lettreL
oul
(ell) ; sinon il est de typeint
( §4.2.1 ). "
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
.
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
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.