# How does implicit conversion work in Java?

Stack Overflow Asked by mohsin ahmed on July 25, 2020

I know that in Java Integer literals are int by default,so if I write something like this

byte byteValue = 2;


Java auto converts the literal value 2(which is an int by default) to byte.
And the same thing works if I write

byte byteValue = 4/2;


The RHS is evaluated as an int and implicitly converted to a byte.

But why doesn’t implicit conversion happen in the below two cases?

int n1 = 4;
byte value = n1/2;


OR in this

byte n1 = 4;
byte value = n1/2;


I know that the RHS of both these examples are evaluated as an int. But why doesn’t Java convert it to a byte implicitly like it did in the first two cases.Does implicit conversion to smaller data type happen only if there are literals?

From doc :

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.

So for your first two case value is constant that why is it's value is representable as the variable type byte.

byte byteValue = 2;
byte byteValue = 4/2;


And for later two case for n1, here n1/2 is not a constant expression, so conversion is not available. So value of n1/2 is not representable in the type of the variable byte.

int n1 = 4;
byte value = n1/2;

byte n1 = 4;
byte value = n1/2;


Answered by User - Upvote don't say Thanks on July 25, 2020

This is documented in §5.2 of the Java Language Specification. That section talks about what conversions are allowed in an assignment context, like the one in byte byteValue = n1/2;.

Assignment contexts allow the use of one of the following:

• ...
• ... (conversions irrelevant to the question)

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.

The conversion from int to byte is a kind of narrowing primitive conversion.

In these cases, the expression on the right hand side are both constant expressions, that is, an expression which the compiler can evaluate at compile time:

byte byteValue = 2;
byte byteValue = 4/2;


So the conversion is applied and the code compiles.

You can see exactly what constitutes a constant expression in §15.28. And you will see that if an expression has a non-final variable like in n1/2, it is not a constant expression. The compiler doesn't want to analyse/run/trace your code to find out what exactly is the value of n1. Therefore, the conversion is not available and the code doesn't compile.

Answered by Sweeper on July 25, 2020

## Explanation

Lets take a look at your code and some modified examples:

// Example 1
byte byteValue = 2;

// Example 2
byte byteValue = 4/2;

// Example 3
byte byteValue = 2000;

// Example 4
byte byteValue = 500/2;

// Example 5
int n1 = 4;
byte byteValue = n1/2;


## Non-lossy conversion

You will get the mentioned compile-time error for Example 3, Example 4 and Example 5.

First of all, the simple math you have for Example 1 to 4 is executed at compile-time. So Java will compute 500 / 2 at compile-time and replace the code with basically byte byteValue = 250;.

Valid values for bytes in Java are -128 to 127. So any value outside of that range can not just be taken as a byte but requires explicit conversion. Because of that, Example 1 and Example 2 pass.

## Lossy narrowing conversion

To understand why the rest fails, we have to study the Java Language Specification (JLS), more specifically chapter 5.1.3. Narrowing Primitive Conversion and 5.2. Assignment Contexts.

It says that a conversion from int to byte (if it is outside of the range of byte) is a narrowing primitive conversion and that it may lose information (for obvious reasons). It continues by explaining how the conversion is done:

A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.

From the second chapter, assignments with narrow conversions are allowed if the value is a constant expression.

In addition, if the expression is a constant expression (§15.29) of type byte, short, char, or int:

A narrowing primitive conversion may be used if the variable is of type byte, short, or char, and the value of the constant expression is representable in the type of the variable.

Long story short, a narrowing conversion that may lose information (because the value exceeds the range) has to explicitly be announced to Java. Java will not just do it for you without you forcing it. That is done by a cast.

So for example

byte byteValue = (byte) (500 / 2);


resulting in the value -6.

## Constant expression

Your last example is very interesting:

int n1 = 4;
byte byteValue = n1/2;


Although this does not exceed the range, Java still treats it as lossy narrowing conversion. Why is that the case?

Well, Java can not ensure 100% that n1 is not changed last second before n1/2 is executed. Therefore, it would have to consider all of your code to see if maybe someone accesses n1 sneaky and changes it. Java does not do this kind of analysis at compile-time.

So if you can tell Java that n1 stays 4 and can actually never change, then this will actually compile. In this specific case, it would be enough to make it final. So with

final int n1 = 4;
byte byteValue = n1/2;


it will actually compile because Java knows that n1 stays 4 and can not change anymore. Hence it can compute n1/2 at compile-time to 2 and replace the code with basically byte byteValue = 2;, which is in range.

So you made n1 / 2 a constant expression, as explained before in 5.2. Assignment Contexts.

You can check the details what it needs to have a constant expression in 15.29. Constant Expressions. Basically everything simple that can easily be computed in place without any method invocations or other fancy stuff.

Answered by Zabuzard on July 25, 2020

This is described in https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.2

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.

Too large a result:

byte byteValue = 100000000/2;

error: incompatible types: possible lossy conversion from int to byte


final variable as an operand:

final byte n1 = 4;
byte value = n1/2;


Answered by Lesiak on July 25, 2020

## Related Questions

### Text is not showing up in Pygame? I tried some other ways to fix but nothing has helped

1  Asked on September 28, 2020 by nathannotnathan

### Android: LiveData postValue() getting null

1  Asked on September 28, 2020 by efoc

### Vimeo offline video playback issue

0  Asked on September 26, 2020 by ipatel

### Firebase Cloud Messaging cURL POST showing error 403

0  Asked on September 26, 2020 by sparsha-dhar

### How to print data from a few arrays

3  Asked on September 25, 2020 by protodimbo

### How to Iterate ‘Values’ of a Nested Dictionary from a Nested Dictionary

2  Asked on September 25, 2020 by psk

### why this.key is not working properly in javacript?

2  Asked on September 25, 2020 by carlos-daniel

### How to delete videos in a Youtube playlist and populate with new videos daily

2  Asked on September 24, 2020 by thepopstream

### Oracle SQL Query to change column headers on basis of conditions from another table

2  Asked on September 23, 2020 by vini

### How do I match groups from Exchange Online to Azure AD?

1  Asked on September 21, 2020 by manuel-k

### Go back and forth on react route without resetting Redux state?

0  Asked on September 21, 2020 by xaovnumwsercy

### UnsupportedDependencyException when running my spring boot application

3  Asked on September 20, 2020 by alan

### Cause of duplicate and missing messages in multithreaded C++ winsock socket?

0  Asked on September 20, 2020 by zachary-zhu

### Pass the dynamic variable when button is pressed

1  Asked on September 19, 2020 by francy

### detect a table part from entire image in python

5  Asked on September 19, 2020 by suji

### linux command line subfolder files batch rename that actually works

1  Asked on September 18, 2020 by fika_fika

### C# Change number of decimals show, but it always skips a number

0  Asked on September 18, 2020 by theoverly

### How can markdown the national flags in jupyter notebook?

1  Asked on September 18, 2020 by mario

### Custom font bold weight not working in Dompdf

1  Asked on September 17, 2020 by user13286

### How to use has one through in laravel?

0  Asked on September 17, 2020 by ahz