I'm using eclipse java ee to perform java programming.
I had the following line of code in one of my functions:
Long result = -1;
I got the following error:
Type mismatch: cannot convert from int to Long
I can't quite understand why when i add a number to the variable it provides this error.
How can this issue be resolved and why did it happen in the first place?
There is no conversion between the object Long and int so you need to make it from long. Adding a L makes the integer -1 into a long (-1L):
Long result = -1L;
However there is a conversion from int a long so this works:
long result = -1;
Therefore you can write like this aswell:
Long result = (long) -1;
Converting from a primitive (int, long etc) to a Wrapper object (Integer, Long etc) is called autoboxing, read more here.
-1 can be auto-boxed to an Integer.
Thus:
Integer result = -1;
works and is equivalent to:
Integer result = Integer.valueOf(-1);
However, an Integer can't be assigned to a Long, so the overall conversion in the question fails.
Long result = Integer.valueOf(-1);
won't work either.
If you do:
Long result = -1L;
it's equivalent (again because of auto-boxing) to:
Long result = Long.valueOf(-1L);
Note that the L makes it a long literal.
First of all, check you Java version: run "java -version" from command line.
In Java version prior to 1.5, the correct syntax is:
Long result = new Long(1L);
In java >1.5 it's done automatically. It's called "autoboxing".
The uppercase "L" tells Java that the number should be interpreted as long.
Long result = -1L;
Long result = (long) -1;
Long result
= Long.valueOf(-1); // this is what auto-boxing does under the hood
How it happened in the first place is that the literal -1 is an int. As of Java5, you can have it auto-boxed into an Integer, when you use it as on Object, but it will not be turned into a Long (only longs are).
Note that an int is automatically widened into a long when needed:
long result = -1; // this is okay
The opposite way needs an explicit cast:
int number = (int) result;
Long result = -1L;
-1 is a primitive int value, Long however is the wrapper class java.lang.Long. An primitive integer value cannot be assigned to an Long object. There are two ways to solve this.
Change the type to long
If you change the type from the wrapper class Long to the primitive type long java automatically casts the integer value to a long value.
long result = -1;
Change the int value to long
If you change the integer value from -1 to -1L to explicit change it to an long literal java can use this primitive value to automatically wrap this value to an java.lang.Long object.
Long result = -1L;
To specify a constant of type long, suffix it with an L:
Long result = -1L;
Without the L, the interpreter types the constant number as an int, which is not the same type as a long.
Related
Why is there a compilation error with Long l = 3 and not with Long l = 3L?
The primitive data type long accepts both 3 and 3l. I understand that 3 is an int literal - but it can't be assigned to a Long wrapper object? int is only 32 bits shouldn't it fit in a 64 bit integer type?
Because there isn't an int to Long widening and autoboxing conversion, autoboxing converts from long to Long (but first the value must be widened from an int to a long). You could do 3L as you have, or
Long l = Long.valueOf(3);
or
Long l = (long) 3;
For additional answer:
3L is equals to (long)3 --> parse it to 3L as it is a long literal
3 is a integer literal
3L is a long literal
in a nutshell, they are different from each other that's why you need to parse int to long or vice versa.
This question already has answers here:
Using the letter L in long variable declaration
(2 answers)
Closed 5 years ago.
What's the difference between the following?
long var1 = 2147483647L;
long var2 = 2147483648;
(or any primitive variable declaration)
Does it have any performance issue with or without L? Is it mandatory?
In the first case you are assigning a long literal to a long variable (the L or l suffix indicates long type).
In the second case you are assigning an int literal (that's the default type when no suffix is supplied) to a long variable (which causes an automatic type cast from int to long), which means you are restricted to the range from Integer.MIN_VALUE to Integer.MAX_VALUE (-2147483648 to 2147483647).
That's the reason why
long var2 = 2147483648;
doesn't pass compilation (2147483648 is larger than Integer.MAX_VALUE).
On the other hand
long var2 = 2147483648L;
would pass compilation.
For easy understanding each of the type have range in java.
By default every digit you entered in java is either byte or short or integer.
short s = 32767;
byte b = 127;
int i = 2147483647;
So if you assign anything except from their range you'll get compilation error.
int i = 2147483648; //compilation error.
Type range
And when you write long longNumber = 2147483647;
though it falls in long range but internally java treat it as
long l = (int) 2147483647;
you wont get any errors.
But if we assign beyond the range of integer like
longNumber = 2147483648; we will get compilation error as
long o = (int) 2147483648;
here java will try to convert the 2147483648 to int but it is not in int range so widening error is thrown.
To indicate java that the number what we have written is beyond the integer range just append l or L to the end of the number.
so java will wide his range till long and convert it as
long o = (long) 2147483648;
By default every floating point or digit with floating points (.) are size of double. So when you write some digits with (.) java treat as a double and it must be in double range.
As we know the float range is smaller then double.
so when you write
float f = 3.14;
though it falls in double range but internally java treat this assignment as
float f = (double) 3.14;
here you are assigning the double to float narrowing which is not correct.
so either you have to convert the expression like that
float f = (float)3.14;
or
float f = 3.14f; // tell jvm to assign this in float range by appending **f** or **F**
If we don't mention the L with the value then value is considered to be int value.
It type casts the int to long automatically.
I have code like this :
int a = 629339;
int b = 4096;
long res = a*b;
The result is -1717194752
but if I add one manual cast to long long res = ((long)a)*b; or long res = (long) a*b; the result is correct 2577772544
Who can explain how does it works.
You have to break the assignment statement into its parts to understand what is doing on:
long res = a*b;
Step 1 is to get the values of a and b.
Step 2 is to evaluate a * b. Since a and b are both ints, this is an int multiplication. So we multiply 629339 by 629339 which would be 2577772544.
Unfortunately, 2577772544 is larger than the largest possible Java int value ... so the multiplication operation silently overflows ... and we get -1717194752 instead.
Step 3 we assign the value of the RHS to the LHS. Since the RHS is int and the LHS is float, the JLS says we perform a primitive widening conversion ... which simply turns -1717194752 into a long with the same value. The widened value is then assigned to res.
To get the answer that you are expecting, we have to force multiplication to be performed using long arithmetic. For example:
long res = ((long) a) * b;
In this case, we have a multiplication of a long by an int, and this is handled by widening the int to a long and performing a long multiply. This no longer overflows (because 2577772544 is well below the largest long value), so when we finally assign the value to res, it is the number that you were expecting.
a*b is an integer, not a long.
Because it's only an integer, it has already wrapped around the 32-bit limit.
Casting this integer back to long will not magically recover that data.
long res = a*b;
a*b will be treated as integer unless you add 'l' at end (or) cast.
As per java tutorial
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive). For integral values, this data type is generally the default choice unless there is a reason (like the above) to choose something else.
In Java programming language widen and boxing doesn't work, but how does it work in following example?
final short myshort = 10;
Integer iRef5 = myshort;
Why does this work? Is this not the same as widen and then box?
But if I write the following code:
final int myint = 10;
Long myLONG = myint;
why it doesn't work?
Following what others have said, I can confirm that I can compile your first example with the Eclipse compiler, but not the second. With the javac compiler, both don't compile, as stated by Vlad
This seems to be a bug in either compiler! Let's consult the JLS to find out, which one is right :-)
With java 7 both the examples are not working. you will get below exception:
Type mismatch: cannot convert from short to Integer
Type mismatch: cannot convert from int to Long
Because the problem is not because of boxing but because of conversion.
You can either widen or box, but you can't do both.
You can do
final int myint = 10;
Long myLONG = (long) myint;
Neither works as it is (using javac 1.6.0_26 from Sun/Oracle, on Linux).
See also here.
b.java:4: incompatible types
found : short
required: java.lang.Integer
Integer iRef5 = myshort;
^
b.java:7: incompatible types
found : int
required: java.lang.Long
Long myLONG = myint;
^
2 errors
Let's examine what you're trying to do in detail:
final short myshort = 10;
Integer iRef5 = myshort;
The compiler will try to first box that short into an object, so that it can then perform the assignment (it cannot widen directly, since it is dealing with different types: an object and a primitive).
In short, this is equivalent to:
final short myshort = 10;
final Short box = new Short(myshort); // boxing: so that objects are assignable.
Integer iRef5 = box; // widening: this fails as Integer is not a superclass of Short
The same reasoning can be applied to your second example (which also fails), as is visible here. If your compiler does not complain on the first one, then there might be a bug with the compiler, because this is what's defined in the JLS. See the complete set of rules for conversion/promotion in the JLS here.
These are the promotion rules that apply to expressions in Java
all byte and short values are promoted to int
If one operand is long,the whole expression is promoted to long
If one operand is a float ,the whole expression is promoted to float
If one operand is double ,the whole expression is promoted to double
Hence short value is promoted to int. This is not widening.
"The conversion of a subtype to one of its supertypes is called widening"
You can box then wide but you can't widen and then box
So
final short myshort = 10;
Integer iRef5 = myshort;
is equivalent to
final short myshort = 10;
Integer iRef5 = 10;
which is perfectly valid
but
Long myLONG = 10;//this won't compile ,
But try with 10L it will so it will box then you can have it object too i.e. Object o = 10L;
See also
boxing-and-widening
scjp-cant-widen-and-then-box-but-you-can-box-and-then-widen
Are you required to define a Long variable as
Long myUserId = 1L; ?
How come you can't just do Long myUserId = 1; ?
Long myUserId = 1; // error
does not work, because 1 is an int.
It will get auto-boxed to:
Integer myUserId = 1; // ok
It will also get widened to:
long myUserId = 1; // also ok
but not both.
So, yes, you have to say
Long myUserId = 1L;
which is a long that can get autoboxed into a Long.
As to why it works that way (or rather does not work in this case): Most likely because auto-boxing was added later (in Java5), and had to be absolutely backwards-compatible. That limited how "smooth" they could make it.
Because otherwise, Java defaults all numeric types to an Integer.
The only reason "1L" is even allowed to be assigned to a Long (instead of the primitive long) is due to the "auto-boxing" introduced with Java 5.
Without the "1L", behind-the-scenes, this looks like the following without the "L":
Long myUserId = Integer.valueOf(1);
... which I hope obviously explains itself. :-)