2

I'm trying to understand the narrowing primitive conversion concept in Java. Here's what the JLS 5.1.3 says about it:

22 specific conversions on primitive types are called the narrowing primitive conversions:

short to byte or char

char to byte or short

int to byte, short, or char

long to byte, short, char, or int

float to byte, short, char, int, or long

double to byte, short, char, int, long, or float

Since there is the implicit conversion converting long to int, we can write the following code:

public static void main (String[] args) throws java.lang.Exception
{
    int c = 88L; //Compilation fail
    System.out.println(c);
}

DEMO

But it doesn't work. Why? The narrowing conversion from long to int should have been applied.

Roy Tinker
  • 10,044
  • 4
  • 41
  • 58
user3663882
  • 6,957
  • 10
  • 51
  • 92

1 Answers1

8

Since there is the implicit conversion converting long to int

There isn't. There's an explicit conversion. Narrowing conversions aren't generally applied implicitly, precisely because they can lose information. So you'd need:

int c = (int) 88L;

Indeed, the initial part of JLS section 5 even gives an example:

// Casting conversion (5.4) of a float literal to
// type int. Without the cast operator, this would
// be a compile-time error, because this is a
// narrowing conversion (5.1.3):
int i = (int)12.5f;

There are some cases where narrowing conversions are applied explicitly in assignment contexts (JLS 5.2) though:

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.

    • ... (similar for Short and Character)

That's why this is valid even though the type of the literal 120 is int:

byte x = 120;

Compare that with widening conversions, which are permitted within assignment contexts and invocation contexts (JLS 5.3).

Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • The spec only says that there are 22 specific conversions on primitives types... and not anymore. – user3663882 Mar 09 '15 at 07:16
  • @user3663882: Not sure what to make of your second comment there. I'm looking at the spec for more about implicit/explicit. – Jon Skeet Mar 09 '15 at 07:17
  • Section 5.2 Assignment Contexts tells what kinds of assignments can be performed without casting. I haven't gone through all the logic but I'm sure it's all there to prohibit long to int conversion even when it is a constant that fits in int. – Atsby Mar 09 '15 at 07:21
  • I think it's not listed there because `char` to `int` is not narrowing. – Atsby Mar 09 '15 at 07:23
  • @user3663882: you know that it is explicit ... by the fact that the compiler gives you an error when trying to go "implicit". – GhostCat Mar 09 '15 at 07:32