Reason for casting a static final short to a short?

556 views Asked by At

I came across something that I didn't fully understand earlier and wondering if someone may be able to shed some light on it.

There is a class file with many static final variables, then they're case to the same type as in the declaration and I wonder why.

So as an example we have:

public static final short A_CONST_VALUE = (short)12;

Thanks.

4

There are 4 answers

6
bonney On

There is no problem in this line public static final short A_CONST_VALUE = (short)12; or public static final short A_CONST_VALUE = 12; if the literal you are specifying is within the range of short which is -32,768 to 32,767. So if you were this line public static final short A_CONST_VALUE = 32768; and compile you will get error "possible loss of precision found: int, required : short" but instead if you write public static final short A_CONST_VALUE = (short)32768; the value of A_CONST_VALUE will be type casted to short and it's value will be -32768 ie it will cycle back.

So as long as the literal is within the range of short, we don't need that typecast.Also the literal that we are assigning to A_CONST_VALUE is not any datatype its just a numeric value and it should lie within the range -32,768 to 32,767 because A_CONST_VALUE is a short dataype. Nuts n bolts of primitive datatype in java

0
Giorgi Tsiklauri On

Although short and int are both integer primitive types, still, they are not the same, and your literal (12) is, by defaul, interpreted as int.

  • short (primitive) is a 16-bit signed two's complement integer, that can store value from inclusive range [-215, 215-1];

  • int (primitive) is a 32-bit signed two's complement integer, that can store value from inclusive range [-231, 231-1].

As you can see, int can store values from a wider range than short, which means, that short is insufficient to store all the values from int.

Therefore, whenever you do narrowing primitive conversion, compiler will do one of these two:

  1. It will implicitly do the conversion for you, behind the scenes, IFF the literal value can fit into the range of the target type it is casted to.
  2. It will ask you to explicitly cast the type IFF the literal value exceeds the range of the target type you want it to be casted to. Why? because, when the literal value exceeds the target range, compiler is unsure about in which specific type you want your value to be casted.. maybe you want to cast it into short.. maybe into byte.. so it's YOU who has to tell this to the compiler.
short a = 32767;
//integer literal 32767 will be automatically converted/casted into "short"

short b = 32768;
//Does NOT compile, as 32768 exceeds "short" range and you need to be explicit, about in which type you want it to be casted, because maybe you want to cast it into the "byte", and not into "short"

byte c = (byte) 32768; //compiles, yet overflows the "byte" type

It is important to understand, that:

Values of the integral types byte, short, int, and long are created from int literals.

So, anytime you do:

long a = 45;
byte b = 2;
short c = 44;

implicit casting applies, and that casting cannot be applied (code will not compile) if the compiler sees, that the literal value exceeds the range of the target type, variable of which, you want to use to store your literal value.

P. S. In your example, explicit casting is semantically redundant, although some may find it nice for syntactical readability purposes.

0
MC Emperor On

It is redundant.

It may have been added for clarity, but in my opinion, it doesn't add any value.

An integer literal without suffix L or l is of type int, according to JLS § 3.10.1:

An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int

So it would require a narrowing conversion to convert an int to a short. But then, according to JLS § 5.2, such a conversion is implicit:

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.

Since 12 is representable in the type short, the conversion is implicit.

So no, the cast is unnecessary, and I think that the same bytecode is generated with or without the cast, although I have not tested this.

0
Stephen C On

You ask why someone would do this:

public static final short A_CONST_VALUE = (short)12;

Well I can't speak for the person who did this, but it is unnecessary.

Lets unpick this:

  1. The public static final modifiers have no bearing on this.

  2. An assignment of a short to a short should not require a cast.

  3. However ... the literal 1 is an integer literal and its type is int not short. (If it was 1L then its type would be long.).

  4. Normally, an assignment of a larger type to a smaller type (e.g. int -> short) does require a type cast to perform a primitive narrowing conversion.

  5. However there is a special rule for assignment contexts:

    • IF the variable's type is byte, char or short
    • AND the value being assigned is the value of a constant expression of type byte, char, short or int
    • AND the value is in the range of the variable's type ....
    • THEN an implicit primitive narrowing conversion is performed.

In simple language, the compiler knows that the assignment is not lossy and does the conversion without you instructing it to.

The relevant part of the Java Language Spec is JLS 5.2 ... starting with "In addition, if the expression is a constant expression ..."