55 votes

Conversion d'un octet en un nombre entier en Java

J'ai généré un nombre aléatoire sécurisé, et mis sa valeur dans un octet. Voici mon code.

SecureRandom ranGen = new SecureRandom();
byte[] rno = new byte[4]; 
ranGen.nextBytes(rno);
int i = rno[0].intValue();

Mais je reçois une erreur :

 byte cannot be dereferenced

1 votes

Il y a une différence entre octet et byte. Ce dernier est un objet, qui supporterait la fonction .intValue() méthode. La première est la valeur brute de l'octet et il suffit de l'assigner comme suit int i = rno[0];

1 votes

99voto

T.J. Crowder Points 285826

Votre tableau est de byte des primitives, mais vous essayez d'appeler une méthode sur elles.

Vous n'avez pas besoin de faire quoi que ce soit d'explicite pour convertir un fichier byte à un int juste :

int i=rno[0];

...puisque ce n'est pas un downcast.

Notez que le comportement par défaut de byte -to- int La conversion consiste à conserver le signe de la valeur (rappelez-vous byte est un type signé en Java). Ainsi, par exemple :

byte b1 = -100;
int i1 = b1;
System.out.println(i1); // -100

Si vous pensiez à la byte comme non signé (156) plutôt que signé (-100), à partir de Java 8 il y a Byte.toUnsignedInt :

byte b2 = -100; // Or `= (byte)156;`
int = Byte.toUnsignedInt(b2);
System.out.println(i2); // 156

Avant Java 8, pour obtenir la valeur équivalente dans le fichier int il faudrait masquer les bits de signe :

byte b2 = -100; // Or `= (byte)156;`
int i2 = (b2 & 0xFF);
System.out.println(i2); // 156

Juste pour être complet, n°1 : Si vous a fait veulent utiliser les différentes méthodes de Byte pour une raison quelconque ( vous n'avez pas besoin d'être ici ), vous pouvez utiliser un conversion à la boxe :

Byte b = rno[0]; // Boxing conversion converts `byte` to `Byte`
int i = b.intValue();

Ou le Byte Constructeur :

Byte b = new Byte(rno[0]);
int i = b.intValue();

Mais encore une fois, vous n'avez pas besoin de ça ici.


Juste pour être complet #2 : Si cela étaient (par exemple, si vous essayiez de convertir une int a un byte ), tout ce dont vous avez besoin, c'est d'un plâtre :

int i;
byte b;

i = 5;
b = (byte)i;

Cela permet au compilateur de savoir que vous savez qu'il s'agit d'un downcast, ce qui évite l'erreur "Possible loss of precision".

47voto

Sheng.W Points 1932
byte b = (byte)0xC8;
int v1 = b;       // v1 is -56 (0xFFFFFFC8)
int v2 = b & 0xFF // v2 is 200 (0x000000C8)

La plupart du temps, la version 2 est celle dont vous avez vraiment besoin.

0 votes

C'est parce que la machine 32 bits a généré le long 0xffffffc8, Merci.

2 votes

C'est la bonne réponse, et v2 est presque toujours ce que vous voulez. La conversion implicite d'un octet en int sans l'option & 0xff est une source de bogues en Java.

1 votes

Ce n'est pas vraiment dû à des "bogues dans Java" de conversion implicite. C'est dû à un malentendu entre développeurs. La primitive byte de Java ne supporte que des valeurs comprises entre -128 et 127. Si quelqu'un essaie d'y insérer une valeur non signée (comme 0xC8), elle peut se retourner avec un tas de uns en tête (en raison de la notation de complément à deux). De même, pour cette question, un espace binaire complet peut avoir un bit de signe activé et une promotion numérique fera de même.

35voto

ratchet freak Points 22412

Si vous voulez combiner les 4 octets en un seul int vous devez faire

int i= (rno[0]<<24)&0xff000000|
       (rno[1]<<16)&0x00ff0000|
       (rno[2]<< 8)&0x0000ff00|
       (rno[3]<< 0)&0x000000ff;

J'utilise 3 opérateurs spéciaux | est le OU logique par bit & est le ET logique et << est le décalage à gauche

en fait, je combine les 4 octets de 8 bits en un seul octet de 32 bits en décalant les octets et en les reliant par OU.

Je m'assure également que toute promotion de signe n'affectera pas le résultat avec & 0xff

4 votes

Je ferais (rno[0]&0x000000ff)<<24|(rno[1]&0x000000ff)<<16| ... etc. pour pouvoir ensuite faire de cet opérande ET une constante. Alternativement, vous pourriez aussi simplement faire ((int)rno[0])<<24|((int)rno[1])<<16| ... car le moulage de type place automatiquement les valeurs d'octets dans l'espace int primitif.

1 votes

@ingyhere Votre suggestion "Alternativement" est incorrecte ! Voir la réponse de Sheng.W. Vous presque toujours il faut faire (b & 0xff) pour convertir un octet en int, et non ((int) b) ou le cast implicite équivalent, à cause de l'extension du signe.

0 votes

Vous m'avez eu @LukeHutchison ... La seconde dans mon commentaire ne fonctionne que pour les valeurs non signées (espace positif) dans la plage de la primitive byte de Java (jusqu'à 127).

8voto

MByD Points 78505

Les types de données primitifs (tels que byte) n'ont pas de méthodes en java, mais vous pouvez le faire directement :

int i=rno[0];

6 votes

Non, c'est Byte.intValue alors que Byte est une classe, byte est un type de données primitif.

0 votes

Cette réponse est incomplète. Voir la réponse de Sheng.W. Vous presque toujours doivent faire (b & 0xff) pour convertir un byte a int pas ((int) b) ou l'équivalent implicite, int i = b; en raison de l'extension du signe pour les octets à nombre de bits élevé. Oublier de faire cela est une source fréquente de bogues.

4voto

joe Points 33

Je pensais que ça le serait :

byte b = (byte)255;
int i = b &255;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X