This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Integer == int allowed in java
What is the difference between the following two statements
Long l1 = 2L;
if(l1 == 2)
System.out.println("EQUAL");
if(l1.longValue() == 2)
System.out.println("EQUAL");
They both are giving same result "EQUAL".But my doubt is Long is object. How is it equal?
As already pointed out in the comments, when doing
if(l1 == 2)
Long l1 gets automatically unboxed to its primitive type, long. So the comparison is between long and int.
In the second case, l1.longValue() will return the long value, as a primitive, of the Long represented by the Long object, so the comparison will be again between long and int. Answering your comment, take a look at What is the main difference between primitive type and wrapper class?
The link given in the comments about autoboxing covers this subject quite well.
This behaviour is explained by widening and boxing.
In the first example,
if(l1 == 2)
what happens is as follows:
1: The compiler notices that you are comparing a wrapper (Long) with a primitive value (int), so it boxes the primitive, resulting in:
if (l1 == new Integer(2))
since 2 is an int (it lacks the 'L' at the end).
2: The compiler now notices that we are comparing a Long with an Integer, so it widens the Integer to a Long, resulting in:
if (l1 == new Long(new Integer(2))
3: Now we are comparing two Longs.
The other case is simpler, here the result is simply:
if (2L == 2)
comparing the primitive values, which is allowed even though they are different types.
Related
This question already has answers here:
Java conditional operator ?: result type
(5 answers)
Why does the ternary operator unexpectedly cast integers?
(3 answers)
Closed 6 years ago.
Please consider we have code below:
Object obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass() + "\nvalue = " + obj);
And its result is:
class java.lang.Long
value = 0
Instead of:
class java.lang.Integer
value = 0
Could someone clarify why we have such functionality in Java? It is very strange for me.
Do you have any example where this can be useful?
UPDATE:
Here is piece of bytecode, where we can see, whats going on there
NEW java/lang/Integer
DUP
LDC "0"
INVOKESPECIAL java/lang/Integer.<init> (Ljava/lang/String;)V
INVOKEVIRTUAL java/lang/Integer.intValue ()I
I2L
INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
ASTORE 1
What's going on here is the result of
Binary numeric promotion turning your Integer and Long types into long for use as the common type to apply to the conditional operator expression
Unboxing those wrapper objects
And then boxing the resulting value of the conditional expression
The conditional operator's second and third operands must end up having the same type, which is the resulting type of the expression. Integer and Long are not, of course, the same type.
However, as described in JLS§15.25, the compiler will apply binary numeric promotion when determining the possible common type to apply to the expression. That section has the handy Table 15.25-D which tells us that when the second operand is of type Integer and the third operand is of type Long, the compiler will do binary numeric promotion on Integer,Long. Binary numeric promotion on Integer,Long yields long. So the result of the conditional operator expression is long.
Since the expression's result type is long, the Integer or Long will have to be unboxed (and then cast, in the case of Integer).
Finally, you assign it to an Object, which forces boxing, and wraps the long in a Long. Thus, you end up with a Long containing the value 0, which matches your output.
So effectively, if we ignore the fact the compiler will optimize half of the following away since it's dealing with a constant expression thanks to the true in the code (I've used flag below instead), that code ends up being this:
Object obj = Long.valueOf(flag ? (long)(new Integer(0)).intValue() : (new Long(1)).longValue());
System.out.println(obj.getClass() + "\nvalue = " + obj);
The (long)(new Integer(0)).intValue() represents unboxing the Integer and casting it to long so it matches the expression result type.
The (new Long(1)).longValue() represents unboxing the Long so it matches the expresion result type.
And the Long.valueOf represents the boxing at the end.
This behavior is well explained in the JLS - 15.25. Conditional Operator ? ::
The conditional operator has three operand expressions. ? appears between the first and second expressions, and : appears between the second and third expressions.
[...]
The type of a conditional expression is determined as follows:
[...]
Otherwise, if the second and third operands have types that are convertible (§5.1.8) to numeric types, then there are several cases:
[...]
Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands.
Actually long can store the value of an integer but integer can not store the value of long(Concept is widening) and you are storing it in Object that's why it's storing it in Long. internally it's also using boxing and unboxing
Possible compiler code:
Long obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass() + "\nvalue = " + obj);
Not working code(unable to compile):
Integer obj = true ? new Integer(0) : new Long(1);
System.out.println(obj.getClass() + "\nvalue = " + obj);
check by yourself and let me know if you havr any doubt in it.
This is related to how the ternary operator works.
The operands on both sides of the : must be of compatible types, so you can't have this:
true ? 1 : "Hello"
Since int and String cannot be implictly converted to each other.
In your case however, the types are compatible! An int can be implicitly converted to long. And that's what the compiler did! It saw an int and a long and decides that the expression should evaluate to a long. It unboxes the two values and implictly convert the int to a long. And finally, it boxes the resulting long so it becomes Long and put it in the variable.
This question already has answers here:
Why is 128==128 false but 127==127 is true when comparing Integer wrappers in Java?
(8 answers)
Closed 6 years ago.
I think that the output should be (true true). Sorry for my english
public class A{
public static void main(String[] args) {
Integer i1 = 128;
Integer i2 = 128;
System.out.println(i1 == i2);
Integer i3 = 127;
Integer i4 = 127;
System.out.println(i3 == i4);
}
}
There is a cache of Integer instances for a range of values (at least -128–127), that is used when implicitly converting an int to an Integer.
In this case, 128 is not in the cache, and so each Integer object representing that value is new and distinct.
The value 127, on the other hand, is guaranteed to be in the cache, and so the same instance of Integer is obtained repeatedly.
Integer, as opposed to the primitive int, is an object. Your comparison is comparing two objects of type Integer. I'm kind of surprised you get "false true". If you instead try:
System.out.println(i1.intValue() == i2.intValue());
System.out.println(i3.intValue() == i4.intValue());
you should get the expected result.
The following code gives error (with IDEA) while I think it shouldn't.
Long[] a = {0L, 0L};
Long[] b = {1L, 1L};
if((a[0] + a[1]).equals(b[1]))
System.out.println("Equal");
Says cannot resolve method equals(java.lang.Long). But it works well with if(a[0].equals(b[0])). I thought that plus operator would return a Long object.
Why does it seem like it doesn't return a Long object, and how are we able to use Long c = a[0] + a[1] if it doesn't return a Long object? Or why can't we use equals like that?
Why does it seem like it doesn't return a Long object?
15.18.2. Additive Operators (+ and -) for Numeric Types tells us that:
Binary numeric promotion is performed on the operands.
The type of an additive expression on numeric operands is the promoted type of its operands.
And 5.6.2. Binary Numeric Promotion tells us that:
If any operand is of a reference type, it is subjected to unboxing conversion.
What this means is that the result of Long + Long is long and we can't call methods on a primitive type.
And how are we able to use Long c = a[0] + a[1] if it doesn't return a Long object?
For Long c = a[0] + a[1], the long is boxed by the assignment.
a[0] + a[1] are added as primitive types and are not autoboxed (primitives do not have methods, hence compile time error). You need to either explicitly wrap them into an object:
(new Long(a[0] + a[1])).equals(b[1])
...or rely on the unboxing of b[1] into a primitive type
a[0] + a[1] == b[1]
(a[0] + a[1])
results in primitive long and not in reference type java.lang.Long.
If you're trying to use a member of a primitive type, that results in a compile time error.
You could use autoboxing, to convert the result of the addition back to Long like this:
((Long)(a[0] + a[1])).equals(b[1])
Long c = (a[0] + a[1]); does something like that "internally", i.e. actually works like this:
Long c = (Long)((long)a[0] + (long)a[1]);
You could also simply unbox b[1]:
(a[0] + a[1]) == b[1]
All you need to do is replace this line:
if((a[0] + a[1]).equals(b[1]))
for this:
if(a[0] + a[1] == b[1])
EDIT:
Yes, you're right - equals can't take sum of longs as parameter, from other answers I can see that it's because they are primitive values. Good to know that, we learn everyday :)
I got a very strange problem when I'm trying to compare 2 Long variables, they always show false and I can be sure they have the same number value by debugging in Eclipse:
if (user.getId() == admin.getId()) {
return true; // Always enter here
} else {
return false;
}
Both of above 2 return values are object-type Long, which confused me. And to verify that I wrote a main method like this:
Long id1 = 123L;
Long id2 = 123L;
System.out.println(id1 == id2);
It prints true.
So can somebody give me ideas?. I've been working in Java Development for 3 years but cannot explain this case.
== compares references, .equals() compares values. These two Longs are objects, therefore object references are compared when using == operator.
However, note that in Long id1 = 123L; literal value 123L will be auto-boxed into a Long object using Long.valueOf(String), and internally, this process will use a LongCache which has a [-128,127] range, and 123 is in this range, which means, that the long object is cached, and these two are actually the same objects.
because == compares reference value, and smaller long values are cached
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
so it works for smaller long values
Also See
Integer wrapper class and == operator - where is behavior specified?
Stuck on an issue for 4 hours because of the use of == ... The comparison was ok on Long < 128 but ko on greater values.
Generally it's not a good idea to use == to compare Objects, use .equals() as much as possible ! Keep ==, >, <, <= etc. for primitives.
This question already has answers here:
Why is == true for some Integer objects? [duplicate]
(4 answers)
Closed 9 years ago.
what is the difference?
public static void main(String[] args){
Integer integer1=1000;
Integer integer2=1000;
System.out.println(integer1==integer2);
}
Result:false
public static void main(String[] args){
Integer integer1=100;
Integer integer2=100;
System.out.println(integer1==integer2);
}
Result:true
We can Try it!
All integers between -128 and 127 are cached, because they are used more often. If you want the first example to work, try:
public static void main(String[] args){
Integer integer1=1000;
Integer integer2=1000;
System.out.println(integer1.equals(integer2));
}
Or, use an int instead of an Integer, as an Integer is an object.
As per JLS 5.1.7:
If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
Integer between -128 to 127 are pooled in Java . Look at this source code :
Integer between -128 to 127 are pooled in java.
Below results in autoboxing and 2 different objects are created:
Integer integer1=1000;integer1 and integer2 are referring to 2 different objects
Integer integer2=1000;
Integer integer1=100;both refer to the same because of pooling
Integer integer2=100;
You have Integer as a reference type. == only compares references when used with objects.
Due to immutability, and interning/pooling, small values of an Integer(within the range [-128, 127] at a minimum, though this is implementation specific and should not be relied upon) may be set to reference the same object.
For the first example, the large numbers forgo interning, ergo different references, and it evaluates to false.
In the second, the Integers are the same reference, and the comparison is true.
You can simply use int instead of Integer and it will work. Otherwise refer to any other answer about == vs equals().