20
byte a = 1;
byte b = 1;
byte c = a + b;

Throws error: possible loss of precision

byte subt = a_s - a_b;
                ^
  required: byte
  found:    int

Is this behavior has something to do with jvm or its been defined in java language .

EDIT : And if it is defined in java language then does it because of keeping jvm in mind ?

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

Radiodef
  • 37,180
  • 14
  • 90
  • 125
Prateek
  • 12,014
  • 12
  • 60
  • 81

6 Answers6

26

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:

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • +1 When the JIT optimises the code to native code, it can use any type it likes. It doesn't have to be an `int` type. – Peter Lawrey Aug 28 '13 at 09:26
  • 1
    Won't Java still be able to convert them to `int`, perform the operation, and convert them back to `byte`? The JLS specification seems more applicable, although this may explain the reasoning behind that part of the JLS. – Bernhard Barker Aug 28 '13 at 09:28
  • @PeterLawrey Will that native code be related to Java? I mean that can be a different language. Am I right? Very little idea about JIT optimization. – Rohit Jain Aug 28 '13 at 09:32
  • @Dukeling. Well a binary operation performed on a int type will result in an int type only. The final result is not a byte type because the result might not fit in it. JLS might not be more applicable, as it doesn't explain the internals of JVM, which is what OP wants I guess. – Rohit Jain Aug 28 '13 at 09:34
  • @RohitJain The native code will be related and produce the same result. Exactly *how* is up to the JIT. If `byte` addition is faster for some reason (which I doubt) it can use that. – Peter Lawrey Aug 28 '13 at 09:35
  • @PeterLawrey. Ok. And what about the instruction set used in that case? which one is used? – Rohit Jain Aug 28 '13 at 09:38
  • @RohitJain The JIT uses the native instruction set of the processor which means it produces different code for different processors (something a static compiler cannot easily do) i.e. it can produce different code for Sandy Bridge vs Haswell and mostly likely will in future versions as Haswell supports HTM. – Peter Lawrey Aug 28 '13 at 09:41
  • @PeterLawrey. Ok. That was what I wanted to know. Now it's clear. Thanks :) – Rohit Jain Aug 28 '13 at 09:42
  • HTM is an interesting topic because it allows the JVM to run synchronized blocks speculatively i.e. concurrently instead of one at a time and detect in hardware if a conflict really occurred or not. (And without needing to recompile the code to use it) – Peter Lawrey Aug 28 '13 at 09:44
13

JLS 5.6.2: Binary Numeric Promotion covers it:

Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

  • If either operand is of type double, the other is converted to double.

  • Otherwise, if either operand is of type float, the other is converted to float.

  • Otherwise, if either operand is of type long, the other is converted to long.

  • Otherwise, both operands are converted to type int.

Community
  • 1
  • 1
Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
12

The compiler is doing the right thing. Because (a + b) can go beyond the maximum value that can be kept in a byte variable. If you tell the compiler a, b values don't change by using the 'final' keyword it wont complain anymore.

final byte a = 1;
final byte b = 1;
byte c = a + b;
Dev Blanked
  • 8,555
  • 3
  • 26
  • 32
0

Yes,It's language spec.

The addition(+) operator. while the adding, 'a' is converts(implicitly casts) to int type, b as well to type int. Hence result is implicitly of type int.

Same for - operator too.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
0

Compiler is right, declare variables to final or cast to byte:

byte b =  1;
byte c =  22;
byte a = (byte) (b + c);

JAVA : byte+byte = int

:)

Narpat Singh
  • 126
  • 8
-1

While doing the arithmetic operations on any operands the result is stored in this form MAX(int,operand1 type,operand2 type,...operandN type) Ex: byte a=10; byte b=20; byte c=a+b;

then result of a+b will be stored in the form of MAX(int,operand1 type,operand2 type,...operandN type) in this case MAX(int,byte,byte) the max value is int which is maximum so c will have the int value but c has been declared as byte, and we can't store int(bigger) value into byte(smaller). the same applies for every arithmetic operator.

that is why the error says error: incompatible types: possible lossy conversion from int to byte

Sushil Patel
  • 113
  • 5