Why Can Not I Add Two Bytes and Get an Int and I Can Add Two Final Bytes Get a Byte

Why can not I add two bytes and get an int and I can add two final bytes get a byte?

From the JLS 5.2 Assignment Conversion

In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int:
- A narrowing primitive conversion may be used if the type of the
variable is byte, short, or char, and the value of the constant
expression is representable in the type of the variable.

In short the value of the expression (which is known at compile time, because it is a constant expression) is representable in the type of the variable that is byte.

Consider your expression

 final byte x = 1;
final byte y = 2;
byte z = x + y;//This is constant expression and value is known at compile time

So as summation fits into byte it does not raise an compilation error.

Now if you do

final byte x = 100;
final byte y = 100;
byte z = x + y;// Compilation error it no longer fits in byte

Is addition of byte converts to int because of java language rules or because of jvm?

if java supports byte datatype then why operation on byte results int

Because that's how the Java Virtual Machine is designed. There is no instruction set to perform operation on a byte type. Rather the instruction set for int type is used for the operation on boolean, byte, char, and short types.

From JVM Spec - Section 2.11.1:

A compiler encodes loads of literal values of types byte and short using Java Virtual Machine instructions that sign-extend those values to values of type int at compile-time or run-time. Loads of literal values of types boolean and char are encoded using instructions that zero-extend the literal to a value of type int at compile-time or run-time. [..]. Thus, most operations on values of actual types boolean, byte, char, and short are correctly performed by instructions operating on values of computational type int.

The reason behind this is also specified in that section:

Given the Java Virtual Machine's one-byte opcode size, encoding types into opcodes places pressure on the design of its instruction set. If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte. [...] Separate instructions can be used to convert between unsupported and supported data types as necessary.

For the details on what all instruction sets are available for various types, you can go through the table in that section.

There is also a table specifying the mapping of actual type to the JVM computational type:

Why explicit cast required when adding int with byte?

27 is a literal. The compiler knows that it is representable in a byte (from -128 to 127).

a + b is an expression involving variables. Its result may not be representable in a byte

How to add two bytes together in Java, with wrap around if there is overflow

Because you're only working with byte, you can store the result of your addition in a larger primitive type, such as an int. By doing this, you'll have easy access to the overflow bit, which you can extract (using bitwise operations) and add to the existing sum:

int sum = b1 + b2;
sum += (sum >> 8) & 1;
String s3 = String.format("%8s", Integer.toBinaryString(sum & 0xFF)).replace(' ', '0');
System.out.println("sum of byte 1 and byte 2: " + s3); // should be 11111111

If the value of the overflow bit is 0, then nothing happens. But if it's 1, overflow occurred and the bit will wrap around.

Why there is no error when a final int is assigned to a byte

When you initialize a final variable with a constant expression, it will become a compile-time constant. Essentially, when the code is compiled, it will just hardcode the value everywhere your variable is added. You can see this in the byte code:

 0  bipush 123
2 istore_1 [i]
3 bipush 123
5 istore_2 [b]

As you can see, it pushes the value 123 directly into the byte (same as byte b = 123), and that is a valid value for a byte. It would not work with a value that is outside the allowed range for bytes.

If the variable is not final (or not initialized with a constant expression), then the compiler will see it as a normal variable, and normal rules for assigning are applied. Meaning that to assign an int to a byte it needs to be casted:

int i = 123;
byte b = (byte) i;

Which produces this bytecode:

0  bipush 123
2 istore_1 [i]
3 iload_1 [i]
4 i2b
5 istore_2 [b]

Is there a more efficient way to combine 2 bytes and get the resulting decimal value?

To concatenate two bytes together efficiently, some bitwise arithmetic is required. However, to achieve the result that you want, we need to operate on the bytes as int values, as the result may be represented by more than 8 bits.

Consequently, we need to ensure that we're always working with the least significant 8 bits of each value (keep in mind that negative integers are represented using leading 1s in binary instead of 0s).

This can be accounted for by performing a bitwise-and of each value with 0xFF:

byte higher = (byte) 0b01110110;
byte lower = (byte) 0b10010010;

int concatenated = ((higher & 0xFF) << 8) | (lower & 0xFF);

System.out.println(concatenated);

As expected, the output of this snippet is:

30354

Why this code is throwing error?

Java does not have an addition operator for bytes, so to compute b1+b2 the values are converted to int and the sum is calculated as with ints. You get the error because there is no implicit conversion from int to byte because of possible loss of precision.

You have to use an implicit casting conversion to get the sum as byte:

b3=(byte)(b1+b2);

By the way, this is not an "exception" but a compile-time error. Exceptions are produced when you run a program.



Related Topics



Leave a reply



Submit