Reputation: 1577
I'm getting compilation error from trivial substraction
Long result;
int operand1 = 10;
int operand2 = 5;
result = operand1 - operand2;
from last line:
incompatible types: int cannot be converted to java.lang.Long
beside the fact that I believe it can be converted what's the best solution to this? Any of the following will compile, but it seems awkward
result = (long) operand1 - operand2;
result = (long) (operand1 - operand2);
result = new Long (operand1 - operand2);
result = Long.valueOf(operand1 - operand2);
Which one is best for performance ?
Upvotes: 0
Views: 6407
Reputation: 9093
Let's look at the byte code generated by javac 1.8.0_66:
(result
is allocated to slot 1, operand1
is in slot 2, and operand2
in slot 3)
Approach 1:
result = (long) operand1 - operand2;
5: iload_2
6: i2l
7: iload_3
8: i2l
9: lsub
10: invokestatic #2 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
13: astore_1
Approach 2:
result = (long) (operand1 - operand2);
14: iload_2
15: iload_3
16: isub
17: i2l
18: invokestatic #2 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
21: astore_1
Approach 3:
result = new Long (operand1 - operand2);
22: new #3 // class java/lang/Long
25: dup
26: iload_2
27: iload_3
28: isub
29: i2l
30: invokespecial #4 // Method java/lang/Long."<init>":(J)V
33: astore_1
Approach 4:
result = Long.valueOf(operand1 - operand2);
This produces the exact same bytecode as Approach 2. Omitted for brevity.
As you can see, all four approaches construct a new Long
object, since Long.valueOf()
will call new Long()
(although Long.valueOf()
caches Long
objects for values between -128 and 127 (in at least Java 1.8.0_66). If the values are outside of that range, calling the constructor is actually a tiny bit faster since it bypasses the cache checks!).
Approach 5: If you're interested in speed, don't use autoboxing, but use primitive types. Here's the change:
long result; // not Long
and the original statement works without complaints from the compiler:
result = operand1 - operand2;
6: iload_3
7: iload 4
9: isub
10: i2l
11: lstore_1
As noted elsewhere on this page, there may be overflow issues: the ints are subtracted first, then converted to a long. It might be best to simply use long
for all 3 types (which will skip the i2l
above).
Upvotes: 3
Reputation: 140554
2 and 4 are basically the same. I wouldn't be surprised if they produce the same bytecode.
1 is going to be pretty much the same as 2 and 4 performance-wise, but it might produce slightly different answers if the integer subtraction in 2 and 4 overflows.
Long.valueOf((long) op1 - (long) op2)
Long.valueOf((long) (op1 - op2))
The only one I would avoid is 3, because this definitely produces a new value, whereas the others might use a cached value, depending upon implementation of Long.valueOf
:
[
Long.valueOf
] returns a Long instance representing the specified long value. If a new Long instance is not required, this method should generally be used in preference to the constructor Long(long), as this method is likely to yield significantly better space and time performance by caching frequently requested values. Note that unlike the corresponding method in the Integer class, this method is not required to cache values within a particular range.
Upvotes: 1
Reputation: 6991
First 2 lines are supposedly best for performance since you are not creating any objects. 'long' is a primitive data type while 'Long' is a wrapper class for long. Between the first two, I'd say that 2nd is a bit faster, since you do the subtraction on ints and then convert a single value to long, whereas in the 1st - you convert both values to long and then do the subtraction of longs which would be a bit slower.
Regarding the compilation issue - primitive types do convert automatically to a larger one, i.e. int would convert to long if you subtract them. However, if you assign a value of that int to a Long class object you'll get compilation error, since the automatic conversion will not happen, so you'll have to manually convert int primitive to long primitive or to Long object.
Upvotes: 1