Couchcamote
Couchcamote

Reputation: 43

Why initialization of new Long Wrapper with int literal is valid?

Looking at the Java Doc for Long, it only has two constructors:

    1) primitive long as param --> new Long(10L);  
    2) String as param --> new Long("23");

But this works new Long(23);

But if the literal is more than the int MAX VALUE (2147483647), the L suffix becomes mandatory so this: ( new Long(2147483648) will now require an L after the value

However: new Long(Integer.MAX_VALUE + 1) is OK

Who can explain this?

Upvotes: 2

Views: 1384

Answers (4)

davidxxx
davidxxx

Reputation: 131376

The differences come from using literal or not.

By using a literal,

long1 = new Long(2147483648)

The code will not compile as the compiler checks the validity of the literal again the type of the variable that receives the literal value and 2147483648 is out of range for an int.
So the compiler emits an error.

It is valid for any literal.
As the compiler expects to have a specific type as value of the literals, so it does the check :

The type of a literal is determined as follows:

The type of an integer literal (§3.10.1) that ends with L or l is long (§4.2.1).

The type of any other integer literal is int (§4.2.1).

...

By using a computation :

long1 = new Long(Integer.MAX_VALUE + 1);

the compiler doesn't check if the size of the Long argument constructor is in the int range.
It is not a literal declaration.
At runtime, an int to long widening primitive conversion occurs.

It produces so a int with Integer.MAX_VALUE + 1 that is -2147483648 (overflow of int) that is converted to a long value.

Upvotes: 0

Pallavi Sonal
Pallavi Sonal

Reputation: 3901

When we write new Long(23) , you can think of it as something like the following happening :

int i = 23;
long l = i; // widening primitive conversion
Long newLong = new Long(l);

Widening conversions are allowed as per the JLS 5.1.2 , so there are no issues with it.

When we try instead , new Long(2147483648) , the first step itself fails, as the value is more than what can fit in an int

 int i = 2147483648;  // doesn't fit in int

When we try new Long(Integer.MAX_VALUE + 1), you can think of it as something like the following happening:

 int i = Integer.MAX_VALUE + 1; // This gives the INTEGER.MIN_VALUE -2147483648
 long l = i ; // widening primitive conversion
 Long newLong = new Long(l);

So, this is allowed. Hope this helps.

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726609

The first part of your question is straightforward: passing int where long is required is allowed because any number that can be represented as an int can also be represented as a long. This is a so-called widening conversion.

The second part, about new Long(Integer.MAX_VALUE + 1), is trickier. Although the widening conversion occurs here as well, it is not of the value that one might think: if you run this program

Long x = new Long(Integer.MAX_VALUE + 1);
System.out.println(x);

you get -2147483648, not the expected 2147483648, because of int overflowing on addition (demo).

The compiler is not smart enough to promote parts of the expression to long before performing addition. Widening conversion occurs after the addition has been performed, on the result of the addition with an overflow.

Upvotes: 4

Raman Sahasi
Raman Sahasi

Reputation: 31851

You can find the answer in javadocs:

A widening primitive conversion from an integral type to another integral type, or from float to double in a strictfp expression (§15.4), does not lose any information at all; the numeric value is preserved exactly.

The integer value 23 can be converted to long 23L without loss of any information at all. Thus with the use of through widening primitive conversions, JVM implicitly converts it to 23L.

So when you call

new Long(23)

It becomes

new Long(23L)

Upvotes: 0

Related Questions