58

I have generated a secure random number, and put its value into a byte. Here is my code.

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

But I am getting an error :

 byte cannot be dereferenced
Oriol Roma
  • 329
  • 1
  • 5
  • 9
Ashwin
  • 12,691
  • 31
  • 118
  • 190
  • 1
    There is a difference between byte and Byte. The latter is an object, which would support the `.intValue()` method. The first is the raw byte value and just assign it like `int i = rno[0];` – wuppi Mar 06 '12 at 10:20
  • 1
    See also http://stackoverflow.com/questions/2383265/convert-4-bytes-to-int – DNA Mar 06 '12 at 10:58

7 Answers7

104

Your array is of byte primitives, but you're trying to call a method on them.

You don't need to do anything explicit to convert a byte to an int, just:

int i=rno[0];

...since it's not a downcast.

Note that the default behavior of byte-to-int conversion is to preserve the sign of the value (remember byte is a signed type in Java). So for instance:

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

If you were thinking of the byte as unsigned (156) rather than signed (-100), as of Java 8 there's Byte.toUnsignedInt:

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

Prior to Java 8, to get the equivalent value in the int you'd need to mask off the sign bits:

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

Just for completeness #1: If you did want to use the various methods of Byte for some reason (you don't need to here), you could use a boxing conversion:

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

Or the Byte constructor:

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

But again, you don't need that here.


Just for completeness #2: If it were a downcast (e.g., if you were trying to convert an int to a byte), all you need is a cast:

int i;
byte b;

i = 5;
b = (byte)i;

This assures the compiler that you know it's a downcast, so you don't get the "Possible loss of precision" error.

sigpwned
  • 6,957
  • 5
  • 28
  • 48
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Using the Byte constructor is not a good idea. Just do `Byte b = rno[0];` instead. – xehpuk Feb 11 '14 at 10:20
  • @xehpuk: I should have mentioned boxing conversions, done that now. – T.J. Crowder Feb 11 '14 at 10:34
  • 1
    Why is boxing conversion superior to Byte constructor in this case? to my understanding the boxing conversion ends up using the Byte constructor in the end any way? is my understanding incorrect? – user1 Nov 30 '17 at 14:57
  • 1
    @user3772575: Yes. Boxing will use `Byte.valueOf`, not `new Byte()`, to avoid allocating a new instance if one already exists for that byte value; [more here](https://docs.oracle.com/javase/9/docs/api/java/lang/Byte.html#valueOf-byte-). (The spec [doesn't actually say that](https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.7), but that's what it does. You can tell by looking at the bytecode.) – T.J. Crowder Nov 30 '17 at 15:43
  • 1
    Last I checked in Java 8 Byte class provides a static method called toUnsignedInt(byte). This should help converting easier and code more readable. – yolob 21 Apr 25 '20 at 12:34
  • @yolob21 - Thanks. Yeah, the answer predated Java 8 by two years. :-) – T.J. Crowder Apr 25 '20 at 12:48
48
byte b = (byte)0xC8;
int v1 = b;       // v1 is -56 (0xFFFFFFC8)
int v2 = b & 0xFF // v2 is 200 (0x000000C8)

Most of the time v2 is the way you really need.

Sheng.W
  • 2,190
  • 16
  • 8
  • it's because the 32 bit machine generated the long 0xffffffc8, Thanks. – herbertD Dec 17 '17 at 16:23
  • 2
    This is the correct answer, and v2 is almost always what you want. Implicit conversion of byte to int without the `& 0xff` is a source of bugs in Java. – Luke Hutchison Dec 06 '18 at 09:44
  • 1
    This isn't really due to "bugs in Java" implicit conversion. It's due to developer misunderstanding. Java's byte primitive only supports values between -128 to 127. If someone tries to stuff an unsigned value (like 0xC8) into that, it can roll over with a bunch of leading ones (due to the twos complement notation). Similarly, for this question, a full bit space can have a sign bit set and a numeric promotion will do similarly. – ingyhere Dec 08 '18 at 01:34
  • Java is actually doing numeric conversion under the hood, [according to the JLS](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.22.1), which means that both operands are converted to int primitives, anyway. – ingyhere Dec 08 '18 at 02:12
  • Not bugs in Java, bugs in user code written in Java :) Most programmers don't realize bytes are signed in Java, and frankly it is a stupid default behavior that they treat bytes as signed in the Java spec, but they did it for consistency with the other integral types, since none of them have unsigned versions. The same problem comes up with conversion of shorts to ints, since people also generally don't realize shorts are signed. (It's easier to trigger sign extension bugs with bytes though, because of the very limited range of values.) People do expect ints and longs to be signed though. – Luke Hutchison Dec 09 '18 at 06:40
36

if you want to combine the 4 bytes into a single int you need to do

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

I use 3 special operators | is the bitwise logical OR & is the logical AND and << is the left shift

in essence I combine the 4 8-bit bytes into a single 32 bit int by shifting the bytes in place and ORing them together

I also ensure any sign promotion won't affect the result with & 0xff

dragi
  • 3,385
  • 5
  • 22
  • 40
ratchet freak
  • 47,288
  • 5
  • 68
  • 106
  • 4
    I would do (rno[0]&0x000000ff)<<24|(rno[1]&0x000000ff)<<16| ... etc. so I can then make that AND-ing operand a constant. Alternately, you could also just do ((int)rno[0])<<24|((int)rno[1])<<16| ... as the type casting automatically puts the byte values into primitive int space. – ingyhere Apr 08 '14 at 15:20
  • 1
    @ingyhere Your "Alternatively" suggestion is incorrect! See Sheng.W's answer. You *almost always* need to do (b & 0xff) to convert a byte to int, not ((int) b) or the equivalent implicit cast, because of sign extension. – Luke Hutchison Dec 06 '18 at 09:42
  • You got me @LukeHutchison ... The second one in my comment only works for unsigned values (positive space) within the range of the Java byte primitive (up to 127). – ingyhere Dec 08 '18 at 01:27
  • The positive range of a signed value is not an unsigned value, it still has the sign of '+' :) Bytes and shorts and ints and longs are signed in Java, there is no unsigned version! – Luke Hutchison Dec 09 '18 at 06:25
8

Primitive data types (such as byte) don't have methods in java, but you can directly do:

int i=rno[0];
MByD
  • 135,866
  • 28
  • 264
  • 277
  • 6
    No, it's `Byte.intValue`, while `Byte` is a class, `byte` is a primitive data type. – MByD Mar 06 '12 at 10:21
  • This answer is incomplete. See Sheng.W's answer. You *almost always* need to do `(b & 0xff)` to convert a `byte` to `int`, not `((int) b)` or the equivalent implicit cast, `int i = b;`, because of sign extension for high-bit-set bytes. Forgetting to do this is a common source of bugs. – Luke Hutchison Dec 09 '18 at 06:30
4

I thought it would be:

byte b = (byte)255;
int i = b &255;
joe
  • 43
  • 2
4

Bytes are transparently converted to ints.

Just say

int i= rno[0];
Saintali
  • 4,482
  • 2
  • 29
  • 49
  • 9
    But note that the sign is preserved, which isn't always what you want (Java doesn't have unsigned bytes) – DNA Mar 06 '12 at 10:53
-2

int b = Byte.toUnsignedInt(a);

  • 2
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 04 '22 at 10:22