Reputation: 43
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
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
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
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
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