web-dev-qa-db-fra.com

Pourquoi ne puis-je pas mettre une valeur hexadécimale dans un tableau d'octets en Java?

Mon code ressemble à ceci:

public byte s[] = {
        0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
        0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
        0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
        0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
        0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
        0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
        0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
        0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
        0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
        0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
        0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
        0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
        0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
        0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
        0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
        0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
    };

Netbeans me dit: 

perte de précision possible - octet requis, trouvé dans l'int

Qu'est-ce que je fais mal? Si j'utilise un court au lieu de l'int, cela fonctionne correctement.

24
Stefan Flondor

Octet est un type de données signé en Java. Il peut prendre des valeurs de -128 (-0x80) à 127 (0x7f). Certaines de vos constantes ne rentrent pas dans cette plage et ne sont donc pas valides pour byte. Cela ne ressemble pas à C++, où BYTE est généralement défini comme étant unsigned char. De plus, Java est beaucoup plus strict sur les conversions de types de données avec une perte de précision.

Donc, 0xF2 n'est pas un littéral byte valide. C'est un short et int et long valide. Java utilise la notion folle de littéraux hexagonaux négatifs pour des valeurs comme celles-ci. Un littéral hexadécimal négatif pour 0xF2 serait -0x0e.

Selon votre situation, utilisez un type de données plus volumineux, ou utilisez une conversion en ligne (telle que (byte)0xF2), ou utilisez quelque chose comme Excel pour convertir vos littéraux de valeur 0x80 et plus en représentation en hexadécimal.

32
Seva Alekseyev

Les octets en Java (comme tous les types de nombres primitifs) sont signés .

La plage valide des valeurs d'octet est comprise entre -128 et 127.

Ainsi, il n'y a pas d'octet qui ait la même valeur que l'entier 0xFF = 255, mais vous avez besoin d'une conversion, ce dont votre compilateur vous avertit. Notez que 255 deviendra réellement -1.

Essayez le code suivant vous-même:

byte test = (byte) 0xFF;
System.out.println(test == 0xFFFFFFFF); // True: -1 == -1 (as int)
System.out.println((byte)0xFF == 0xFFFFFFFF); // True: -1 == -1 (as int)
System.out.println(0xFF == (byte) 0xFFFFFFFF); // False: +255 != -1 (as int)
System.out.println((byte)0xFF == (byte) 0xFFFFFFFF); // True: -1 == -1 (as byte)
byte warn = (byte) 0xFF; // "error: possible loss of precision" unless cast
byte nowarn = -0x1; // No error. -0x1 is a *valid* byte in Java!
System.out.println(warn == nowarn); // True: -1 == -1 (as bytes)
System.out.println((int)warn == (int)nowarn); // True: -1 == -1 (as int, too)

Ceci devrait afficher true, true, false, true, true, true comme indiqué.

Vous devez réalisez que ==, lorsqu'il est appliqué à byte == int, convertit l'octet (signé) en un entier (signé), et byte -1 doit bien sûr devenir int -1.

10
Anony-Mousse

En guise d'alternative, vous écrivez dans Java 7 des littéraux d'octets en notation binaire. par exemple. 0b101 est 5.

3
Dunes

Il suffit de lancer chaque octet:

byte a[]={(byte)0x01,(byte)0x01,(byte)0x01,}
2
wahid

Au lieu de prendre 0XFF, nous pourrions utiliser 0X7F et suivre le code comme ci-dessous

byte[] ba = new byte[charArray.length*2];
int j = 0;
byte mask = (byte) 0x7f;
System.out.println("mask value is:" + mask);

for (int i = 0; i < charArray.length; ++i, j+=2) {
    byte upper8bits = (byte) ((byte)(charArray[i] >> (1<<3)) & mask);
    byte lower8bits = (byte) ((byte) charArray[i] & mask);
    ba[j] = upper8bits;
    ba[j+1] = lower8bits;
    System.out.println("byte[]:" + Integer.toHexString(ba[j+1]));
}
0
user2089997