1

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.

null
  • 3,469
  • 7
  • 41
  • 90
  • 2
    Looks completely redundant at first sight. I doubt that it generates any bytecode different than it would if you take it out. – Jorge_B Jun 26 '15 at 10:26
  • 1
    You can refer to this thread http://stackoverflow.com/questions/769963/javas-l-number-long-specification – Johnson Abraham Jun 26 '15 at 10:28
  • 1
    do you know why we put F on float and L on long.. i think the same reason – subash Jun 26 '15 at 10:28
  • @Jorge_B It does seem odd, I wonder if perhaps there's some other reason for it. The numbers range from 1 to 650 or so but...I don't know, just seems odd. – null Jun 26 '15 at 10:28
  • @SteveGreen it makes no difference to use a cast or not in this case (apart from the unnecessary clutter). – assylias Jun 26 '15 at 10:45
  • 1
    You do not need the cast for this value - at least in recent versions of Java. The rules are described in the Java 8 language spec - see [Assignment Contexts](https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.2). – McDowell Jun 26 '15 at 10:47

4 Answers4

2

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.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
1

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.

Giorgi Tsiklauri
  • 9,715
  • 8
  • 45
  • 66
0

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

bonney
  • 455
  • 4
  • 7
  • Yes but why might it be? I imagine this to be written by fairly good devs and then maintained for many years. – null Jun 26 '15 at 11:45
  • Future proofing in the case of exceeding the short value seems a bit extreme. – null Jun 26 '15 at 11:46
  • Could you please elaborate "but why might it be" 'cos if you will help me understand your doubt i could possibly help – bonney Jun 26 '15 at 11:49
  • Well, I guess I'm mainly trying to understand the thought process or reasoning behind including the cast. In all scenarios (exc the obscene future proof) it just doesn't seem to make sense. – null Jun 26 '15 at 11:55
  • The above casting is uneccessary acc. to me beacuse the value 12 can be stored in two bytes (since short is 16-bit) so there is no need for explicit type casting.Its needed when we write int a = 20; – bonney Jun 26 '15 at 19:24
  • short b = (short) a; Now here explicit casting is needed because 'a' is holding a 4 byte value which we want to store in 'b' a 2 byte space of memory – bonney Jun 26 '15 at 19:31
0

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 ..."

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216