Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Primitive cast and assignments in Java

Tags:

java

I understand why the following is wrong:

byte a = 3;  byte b = 8;  byte c = a + b;  // compile error 

It won't compile. Expressions always result in an int. So we should have done the explicit cast:

byte c = (byte) (a + b);   // valid code 

But I don't understand why the following is correct:

byte d = 3 + 8;   // it's valid! why? 

Because literal integer (such as 3 or 8) is always implicitly an int. And int-or-smaller expressions always result in an int too. Can anybody explain what is going on here?

The only thing I can guess is that the compiler equates this expression to the following:

byte d = 11; 

and doesn't consider this an expression.

like image 939
Alex Avatar asked Jun 14 '13 14:06

Alex


People also ask

What is primitive casting in Java?

Casting between primitive types enables you to convert the value of one type to another primitive type is called Primitive Type Casting. This is most commonly occurs with the numeric data types . But boolean primitive type can never be used in a cast.

What are primitive data types in Java?

Primitive data types - includes byte , short , int , long , float , double , boolean and char.

How many primitive data types are there in Java?

The eight primitive data types supported by the Java programming language are: byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive).

Which of the following primitive data type Cannot be casted?

Casting Primitive Types It most commonly occurs with the numeric types, and there's one primitive type that can never be used in a cast. Boolean values must be either true or false and cannot be used in a casting operation.


2 Answers

This has less† to do with whether or not 3 + 8 is evaluated to 11 at compile-time, and more to do with the fact the compiler is explicitly permitted to implicitly narrow ints to bytes in certain cases. In particular, the language specification explicitly permits implicit narrowing conversions to byte of constant expressions of type int that can fit in a byte at compile-time.

The relevant section of the JLS here is section §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.

The compile-time narrowing of constants means that code such as: byte theAnswer = 42; is allowed. Without the narrowing, the fact that the integer literal 42 has type int would mean that a cast to byte would be required:

†: Obviously, as per the specification, the constant expression needs to be evaluated to see if it fits in the narrower type or not. But the salient point is that without this section of the specification, the compiler would not be permitted to make the implicit narrowing conversion.

Let's be clear here:

byte a = 3;  byte b = 8;  

The reason that these are permitted is because of the above section of the specification. That is, the compiler is allowed to make the implicit narrowing conversion of the literal 3 to a byte. It's not because the compiler evaluates the constant expression 3 to its value 3 at compile-time.

like image 123
jason Avatar answered Sep 21 '22 21:09

jason


The only thing I can guess is that the compiler equates this expression to the following:

Yes it does. As long as the right side expression is made of constants (which fit into the required primitive type -- see @Jason's answer for what the JLS says about this exactly), you can do that. This will not compile because 128 is out of range:

byte a = 128; 

Note that if you transform your first code snippet like this:

final byte a = 3;  final byte b = 8;  byte c = a + b; 

it compiles! As your two bytes are final and their expressions are constants, this time, the compiler can determine that the result will fit into a byte when it is first initialized.

This, however, will not compile:

final byte a = 127; // Byte.MAX_VALUE final byte b = 1; byte c = a + b // Nope... 

The compiler will error out with a "possible loss of precision".

like image 44
fge Avatar answered Sep 23 '22 21:09

fge