Why Byte += 1 Compile But Byte = Byte + 1 Not

why byte += 1 compile but byte = byte + 1 not?

Because b += 1 is an equivalent to b = (byte)(b + 1), whereas type of b + 1 is promoted to int (JLS §5.6.2 Binary Numeric Promotion) and therefore its result cannot be assigned to byte without explicit conversion.

From JLS, §15.26.2 Compound Assignment Operators:

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

Why b=b+1 when b is a byte won't compile but b+=1 compiles

This is an interesting question. See JLS 15.26.2. Compound Assignment Operators:

A compound assignment expression of the form E1 op= E2 is equivalent
to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1
is evaluated only once.

So when you are writing b+=1;, you are actually casting the result into a byte, which is the similar expressing as (byte)(b+1) and compiler will know what you are talking about. In contrast, when you use b=b+1 you are adding two different types and therefore you'll get an Incompatible Types Exception.

Why does the compiler not give an error for this addition operation?

The answer is provided by JLS 15.26.2:

For example, the following code is correct:

short x = 3;

x += 4.6;

and results in x having the value 7 because it is equivalent to:

short x = 3;

x = (short)(x + 4.6);

So, as you can see, the latest case actually work because the addition assignment (as any other operator assignment) performs an implicit cast to the left hand type (and in your case a is a byte). Extending, it is equivalent to byte e = (byte)(a + b);, which will compile happily.

Java byte type is weird?

b6 does work due to compile-time narrowing of literal constants. b7 does not work because compile-time narrowing is limited to all primitives but long (kind of strange, no idea why)

The interesting part is §5.2 of the JLS:

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.
A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is :

- Byte and the value of the constant expression is representable in the
type byte.

- Short and the value of the constant expression is representable in
the type short.

- Character and the value of the constant expression is representable in the type char.

If the type of the expression cannot be converted to the type of the variable by a conversion permitted in an assignment context, then a compile-time error occurs.

No idea why i does not work though - widening should work just fine and in fact, the compiler should generate something like Integer.valueOf((byte)3); anyhow. Using the explicit call works as expected, i.e. widening is happening.

Interestingly enough using the eclipse Java compiler Integer i = (byte) 3; compiles just fine, which leads me to believe you just found a bug in javac - congratulations! (well either that or a bug in the eclipse compiler; but eclipse's behavior seems the correct one to me). FWIW I've reported the bug against javac to oracle..

Finding the right part in the JLS was less work than formatting this that it's somewhat readable - so probably easier if you follow the link instead.

How to fix Invalid byte 1 of 1-byte UTF-8 sequence

How to fix this issue ?

Read the data using the correct character encoding. The error message means that you are trying to read the data as UTF-8 (either deliberately or because that is the default encoding for an XML file that does not specify <?xml version="1.0" encoding="somethingelse"?>) but it is actually in a different encoding such as ISO-8859-1 or Windows-1252.

To be able to advise on how you should do this I'd have to see the code you're currently using to read the XML.

unable to increment byte value with expression but with increment operator

Whenever you perform a binary operation between two operands of different types, one of the operands is promoted to the higher type. And then the result of the operation is of that type.

So, in your case, the byte type a is first promoted to an int, since 1 is an int type. And then after the addition operation, the result is of type int. Now, since you cannot assign an int to a byte, you need to do a typecast to remove the compiler error:

byte a = 2;
a = a + 1; // Error: Cannot assign an int value to byte
a = (byte)(a + 1); // OK

Now, in case of Compound Assignment Operator, the typecasting is done implicitly for you. The expression:

a += 1

is internally converted to:

a = (byte)(a + 1);

This is specified in JLS - §15.26.2 Compound Assignment Operator:

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

Similar is the case with prefix increment operators, and postfix increment operators.

According to JLS - §15.15 Unary Operators:

The type of the prefix increment expression is the type of the variable.

Why is int i = 2147483647 + 1; OK, but byte b = 127 + 1; is not compilable?

Constants are evaluated as ints, so 2147483647 + 1 overflows and gives you a new int, which is assignable to int, while 127 + 1 also evaluated as int equals to 128, and it is not assignable to byte.

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]


Related Topics



Leave a reply



Submit