Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is an implicit narrowing conversion allowed from int to byte but not from long to int?

Tags:

java

Consider the below code snippet:

// automatic casting works for int to byte conversion as integer literal 127
// is in the range for byte
byte b1 = 127; //OK

// automatic casting doesn't work for long to int conversion 
// even if long literal is in the range of int.
int i5 = 100L; // NOT OK - compilation error

Is there any explanation for such behavior?

Why is explicit conversion not needed in the case of int to byte, but needed for long to int?

The How does Java convert int into byte? question is different. It is about an issue in implicit conversion of int to byte when the int value is out of range.

like image 294
Kanad Avatar asked Dec 29 '17 16:12

Kanad


People also ask

What happens when int is converted to byte?

lang package converts the given Integer into a byte after a narrowing primitive conversion and returns it (value of integer object as a byte). Also, remember this method does override byteValue() method of the Number class. Return Type: Returns the numeric value represented by this object after conversion to byte type.

What is the effect of converting an integer to byte justify?

When an integer value is converted into a byte, Java cuts-off the left-most 24 bits. We will be using bitwise AND to mask all of the extraneous sign bits.

Are narrowing conversions allowed in Java?

Core Java bootcamp program with Hands on practiceNarrowing conversion is needed when you convert from a larger size type to a smaller size. This is for incompatible data types, wherein automatic conversions cannot be done. Let us see an example wherein we are converting long to integer using Narrowing Conversion.

What is the difference between narrowing conversion and widening conversion?

Widening conversions preserve the source value but can change its representation. This occurs if you convert from an integral type to Decimal , or from Char to String . A narrowing conversion changes a value to a data type that might not be able to hold some of the possible values.


1 Answers

Widening conversions (eg. byte to int) are generally accepted implicitly by the Java compiler, as there's no loss of information (the range of int is greater than that of byte).

Narrowing conversions (eg. long to int, as in your case) can cause a loss of information, so are generally required to be explicitly casted.

See this similar question, and this. A relevant piece of the Java Language Specification:

Assignment conversion occurs when the value of an expression is assigned (§15.26) to a variable: the type of the expression must be converted to the type of the variable.

...

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.

(emphasis mine)


Some confusion stems from the fact that we're dealing in particular with constant expressions, as we're using numeric literals. The above spec also needs some careful reading.

To clear some things up and directly answer some of the OP's queries:

  1. Why implicit narrowing is supported for one type of narrowing and not the other?

    Ie. why does byte b1 = 127 work implicitly, while int i5 = 100L not?

    byte b1 = 127 performs an implicit conversion as (cf. the bold text in the above quote), "the value of the constant expression is representable in the type byte". That is, 127 is representable by a byte, so the conversion is implicit. If you try byte b1 = 128, you'll get an error about incompatible types, as 128 isn't representable by byte. The only reason we're allowed an implicit cast here at all is because we're using a constant expression.

    We don't get an implicit conversion in int i5 = 100L (even though 100 is in the range of int) as that's simply not listed in the allowed implicit conversions (the variable's type, int, is not one of byte, short, or char).

    We also don't get an implicit conversion in byte a = 0L, this time as the constant expression is of type long, not of type byte, short, char, or int.

  1. How will a normal programmer know which narrowing conversion is allowed implicitly?

    The implicit narrowing conversions only occur when you're assigning a constant expression to a variable. In these cases, implicit conversions are good as we don't want to be writing code like byte b = (byte)0 all the time. At the same time, we do want to be warned if we write something like byte b = 128, as that doesn't have intuitive behaviour.

    When we're not assigning constant expressions (so eg. int x = 0; byte b = x;), we always want to be warned when we're doing a potentially lossy conversion, as they're dangerous - so explicit conversions in this case also make sense.

like image 164
hnefatl Avatar answered Sep 22 '22 08:09

hnefatl