Weird equality behavior in java [duplicate] - java

This question already has answers here:
Weird Integer boxing in Java
(12 answers)
Closed 8 years ago.
Take a look at following code:
Long minima = -9223372036854775808L;
Long anotherminima = -9223372036854775808L;
System.out.println(minima==anotherminima); //evaluates to false
System.out.println(Long.MIN_VALUE);
Long another= 1L;
Long one = 1L;
System.out.println(another == one); //evaluates to true
I am not able to understand this behavior..? I was hoping the first eval to be true as well..
And that is what I am expecting..

There is a caching technique used by the JVM for some range of autoboxing value. As specified in the spec ( http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7 )
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
Ideally, boxing a given primitive value p, would always yield an identical reference. In practice, this may not be feasible using existing implementation techniques. The rules above are a pragmatic compromise. The final clause above requires that certain common values always be boxed into indistinguishable objects. The implementation may cache these, lazily or eagerly. For other values, this formulation disallows any assumptions about the identity of the boxed values on the programmer's part. This would allow (but not require) sharing of some or all of these references.
This ensures that in most common cases, the behavior will be the desired one, without imposing an undue performance penalty, especially on small devices. Less memory-limited implementations might, for example, cache all char and short values, as well as int and long values in the range of -32K to +32K.
So 1L is in this cached values and then the autoboxing give the exact same reference, but in the case of the number outside of this range (like the Long.MIN_VALUE) it isn'T cached and thus a different instance/reference is given.
In any case, when comparing object you should always use .equals()

Just a guess here, but it could be that 1L is in the constant pool, and thus the reference equality evaluates to true (just like how sometimes, even by Strings, == will evaluate to true), while that other huge number isn't. Not sure how to check which constants are in the pool at initiation.
Edit: Java has a cache of certain constant objects (including the wrapper classes for primitives, and String). Thus, if you write
String st1 = "A";
if "A" is in the constant pool, Java won't create a new String object- it will just create a reference to the already existing one. So if you then did
String st2 = "A";
System.out.println(st1 == st2);
It would print out true.
Now, not all Integer, Long, Short, etc... are cached (there are way too many), but the lower values are. So I would assume that 1L is. That means that in your question, both another and one refer to the same object, and thus it returns true even for reference equality.

First of all you should use long instead of Long. Secondly == between Integer, Long etc will check for reference equality. You may check the 5.1.7 Boxing Conversion. Alo 1L is in the constant pool so the second case is returning true.
On a side note you should use .equals for comparing the long.
From the Oracle docs:
If the value p being boxed is true, false, a byte, or a char in the
range \u0000 to \u007f, or an int or short number between -128 and 127
(inclusive), then let r1 and r2 be the results of any two boxing
conversions of p. It is always the case that r1 == r2.
Ideally, boxing a given primitive value p, would always yield an
identical reference. In practice, this may not be feasible using
existing implementation techniques. The rules above are a pragmatic
compromise. The final clause above requires that certain common values
always be boxed into indistinguishable objects. [...]
This ensures that in most common cases, the behavior will be the
desired one, without imposing an undue performance penalty, especially
on small devices. Less memory-limited implementations might, for
example, cache all char and short values, as well as int and long
values in the range of -32K to +32K.

Adding on to this answer, everything from -128 to 127 is cached into an instance in permanent java memory, meaning that those numbers (almost) always have reference equality, because new instances are not created for them. Outside of the cache, a new instance is created every time the number is used, so they are not equal referentially. Read more here and here

problem:
(minima==anotherminima)
You are comparing the memory location of the object not its values thus it returns false.
If you want to compare two long wrapper class you need to call compareTo
From jls
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f,
or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results
of any two boxing conversions of p. It is always the case that r1 == r2.
Now if you use -128 and 127 to initialized the Long wrapper class it will result to boxing conversion which will have the same reference.

You should use long instead of Long. Note that Long is a class and so you must use equals() to compare instances of it. On the other hand, if you use long instead, you can compare with == because these are primitives.

Related

how does == operator in java works for primitive types [duplicate]

This question already has answers here:
how equal operator works with primitive and object type data
(2 answers)
Closed 8 months ago.
I was reading about == operator and I noticed it says it is used for reference comparison. But then how does it work when we have a condition like
int i = 5;
if (i == 5){
.....
}
i being int primitive type.
Does it gets converted to Integer wrapper class behind the scene and the It behaves like strings immutable class meaning even if we hard code value it will point to the same object in memory?
This operator is actually the 'primitive' comparison that exists on machine language level. To compare two values, load one of them into a CPU register, then subtract the other value and see if all bits are zero.
This comparison works for boolean, numbers, characters - anything you can put into a memory location that is not bigger than the CPUs register. In Java such data types are called primitive types. Today most machines have 64 bits which is the magic size limitation.
Since Objects and Arrays can easily exceed that given size, a pointer to their memory location is passed instead. The primitive comparison would now compare two Objects by comparing their memory pointers. But it is not smart enough to compare the Object content.
So if you have two Objects in different addresses that both have the same value the == comparison will fail, although most people think the result should be true. That's why Java has both == operator and the .equals method.

Java PriorityQueue behaviour with int[] vs. List<Integer> [duplicate]

As of Java 1.5, you can pretty much interchange Integer with int in many situations.
However, I found a potential defect in my code that surprised me a bit.
The following code:
Integer cdiCt = ...;
Integer cdsCt = ...;
...
if (cdiCt != null && cdsCt != null && cdiCt != cdsCt)
mismatch = true;
appeared to be incorrectly setting mismatch when the values were equal, although I can't determine under what circumstances. I set a breakpoint in Eclipse and saw that the Integer values were both 137, and I inspected the boolean expression and it said it was false, but when I stepped over it, it was setting mismatch to true.
Changing the conditional to:
if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt))
fixed the problem.
Can anyone shed some light on why this happened? So far, I have only seen the behavior on my localhost on my own PC. In this particular case, the code successfully made it past about 20 comparisons, but failed on 2. The problem was consistently reproducible.
If it is a prevalent problem, it should be causing errors on our other environments (dev and test), but so far, no one has reported the problem after hundreds of tests executing this code snippet.
Is it still not legitimate to use == to compare two Integer values?
In addition to all the fine answers below, the following stackoverflow link has quite a bit of additional information. It actually would have answered my original question, but because I didn't mention autoboxing in my question, it didn't show up in the selected suggestions:
Why can't the compiler/JVM just make autoboxing “just work”?
The JVM is caching Integer values. Hence the comparison with == only works for numbers between -128 and 127.
Refer: #Immutable_Objects_.2F_Wrapper_Class_Caching
You can't compare two Integer with a simple == they're objects so most of the time references won't be the same.
There is a trick, with Integer between -128 and 127, references will be the same as autoboxing uses Integer.valueOf() which caches small integers.
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.
Resources :
JLS - Boxing
On the same topic :
autoboxing vs manual boxing java
"==" always compare the memory location or object references of the values. equals method always compare the values. But equals also indirectly uses the "==" operator to compare the values.
Integer uses Integer cache to store the values from -128 to +127. If == operator is used to check for any values between -128 to 127 then it returns true. for other than these values it returns false .
Refer the link for some additional info
Integer refers to the reference, that is, when comparing references you're comparing if they point to the same object, not value. Hence, the issue you're seeing. The reason it works so well with plain int types is that it unboxes the value contained by the Integer.
May I add that if you're doing what you're doing, why have the if statement to begin with?
mismatch = ( cdiCt != null && cdsCt != null && !cdiCt.equals( cdsCt ) );
The issue is that your two Integer objects are just that, objects. They do not match because you are comparing your two object references, not the values within. Obviously .equals is overridden to provide a value comparison as opposed to an object reference comparison.
Besides these given great answers, What I have learned is that:
NEVER compare objects with == unless you intend to be comparing them
by their references.
As well for correctness of using == you can just unbox one of compared Integer values before doing == comparison, like:
if ( firstInteger.intValue() == secondInteger ) {..
The second will be auto unboxed (of course you have to check for nulls first).

why two primitive doubles with same value have two different identityHashCode?

I learned that all primitives with same value have same identityHashCode so, I wanted get identityHashCode of some primitives.so when I tried with 2 doubles with same value it was giving different identityHashCode I did following:
int xInt=5;
int yInt=5;
System.out.println(System.identityHashCode(xInt));//output:1867083167
System.out.println(System.identityHashCode(yInt));//output:1867083167
double double1=5;
double double2=5;
System.out.println(System.identityHashCode(double1));//output:1915910607
System.out.println(System.identityHashCode(double2));//output:1284720968
two ints with same value have same identityHashCode but two doubles with same value have different identityHashCode why is that?
Your code is boxing the primitive values. (The primitive values themselves don't have an identity hash code, as that's only a concept that's relevant for objects.) Your code is equivalent to this:
int xInt=5;
int yInt=5;
Integer xInteger = xInt;
Integer yInteger = yInt;
System.out.println(System.identityHashCode(xInteger));
System.out.println(System.identityHashCode(yInteger));
double double1=5;
double double2=5;
Double boxedDouble1 = double1;
Double boxedDouble2 = double2;
System.out.println(System.identityHashCode(boxedDouble1));
System.out.println(System.identityHashCode(boxedDouble2));
Now if you compare the references themselves, you'll see that xInteger == yInteger is true, but boxedDouble1 == boxedDouble2 is false... so identityHashCode is representing that relationship accurately.
The reason your boxed integer references refer to the same object is that boxed integral types within a particular range are cached:
If the value p being boxed is the result of evaluating a constant expression (§15.28) of type boolean, char, short, int, or long, and the result is true, false, a character in the range '\u0000' to '\u007f' inclusive, or an integer in the range -128 to 127 inclusive, then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.
The range can actually be bigger in practice, and an implementation could cache boxed doubles as well, but I haven't seen that happen.
i learned that all primitives with same value have same identityHashCode
That can't be true, since primitives, by definition, are not objects, and thus don't have an identity hash code in the first place.
When you're calling System.identityHashCode(), the argument is boxed to an Integer or a Double.
And Integer boxing uses a cache for the frequently used integers (from -128 to 127 by default). That's not the case for Double boxing.
Try it with a large int, and you'll get different results, too.
There's a boxing issue at play here - you can't compare primitive datatypes with identityHashCode as it uses Object as its parameter.
Returns the same hash code for the given object as would be returned
by the default method hashCode()
But of course double isn't the same as Double.
i learned that all primitives with same value have same identityHashCode.
There are at least two misconceptions there. First, primitives don't have hash codes or identity hash codes at all. It is Objects that do, such as the wrapper objects obtained by autoboxing primitive values.
Second, the overall idea is simply wrong, as your own experiment demonstrates. If you provide a primitive as the argument to System.identityHashCode() then it is autoboxed into an instance of the appropriate wrapper class, and the identity hash code of the resulting object is returned. An object's identity hash code is uniquely characteristic of that object during its lifetime, and independent of its state. No two objects existing at the same time have the same identity hash code. What's more interesting, then, is not that you get different identity hash codes for the autoboxed doubles, but that you get the same identity hash codes for autoboxed small integers.
In fact, this shows that Java maintains a cache of Integer objects for small integer values. It uses these when autoboxing values in the range covered, and when handling explicit Integer.valueOf() invocations for those values. Thus, in your example, you get the same object each time you autobox the integer 5, and you see the same identity hash code. If you used a sufficiently large value then you would not see the same effect.
Java does not perform such caching for the Doubles with value 5.0.
On the other hand, perhaps you simply misunderstood the lesson. Distinct wrapper objects representing the same primitive type and value don't have the same identity hash code, but they do have the same (regular) hash code, because that, for the wrapper classes, is determined by the primitive values they represent. So compare the results of your code to the results of this:
System.out.println(Double.valueOf(double1).hashCode());
System.out.println(Double.valueOf(double2).hashCode());

Why same values got from ArrayList are changed to different ones?

I am using Java ArrayList.
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(-129);
list.add(-129);
return (list.get(0) == list.get(1));
The return value is false.
I know it must be some range problem since when I use -128, it returns true.
But could someone tell me the reason of it?
Java caches integers in the range -128..127 (signed bytes). It saves a lot of allocations of tiny numbers which is very common in lots of code. If you use equals() instead of ==, it will work. The == check is comparing that two int types, that have been magically boxed (i.e. converted) to Integer are the same reference - which they are not. But int in the signed byte range will be the same. The equals check will actually compare the value of the variables:
return (list.get(0).equals(list.get(1)));
When you perform:
list.add(-129);
list.add(-129);
It create two separate object with separate memory location.when you perform == it return false.
In Java, values from -128 to 127 are cached, so the same objects are returned and you will get true.
For more information see:http://www.geeksforgeeks.org/comparison-autoboxed-integer-objects-java/
If two references point to two different objects, then in accordance with the "= =" to judge both is unequal, even though both have the same reference content. As we know, if two references refer to the same object, in accordance with the "= =" to judge the two are equal.
If you go to the Integer. Java classes, you will find that there is a internal private class IntegerCache. Java, it caches from all the Integer object - between 128 ~ 127.
So the thing is, all the small integers are in the internal cache.
If the value is between 128 ~ 127, then it will be returned from a cache instance,point to the same object.

Why does comparing Integers by reference (==) work?

In Herbert Schildt's "Java: The Complete Reference, 9th Edition", there's an example that kinda baffles me. Its key point that i can't comprehend could be summed up to the following code:
class Test {
public static void main (String args[]) {
Integer i1 = 6;
Integer i2 = 6;
Integer i3 = 6;
Integer i4 = (args.length + 1) * 6;
if (i1 == i2) System.out.println("WTF");
if (i3 == i4) System.out.println("Super WTF!!!");
}
}
To my surprise, the result of compiling and executing such code using JDK 8 update 40 is as follows:
WTF
Super WTF!!!
All the Java books, manuals and other informational resources that i've seen state that the equality operator (==), when used to compare objects, simply matches their reference values. So, if two object variables refer to distinct instances, then the == operator returns false, even if the internal contents of those objects are the same. Which is quite different from the behavior expressed by the example above.
While checking SO for similar questions, i found a somewhat related one, which is about comparing String objects using ==. There, an interesting feature of Java called interning was mentioned. Apparently, all the string literals and compile-time string constants are sort of "cached" by JVM, so that, for example, multiple String references initialized with the same string literals actually point to the same object.
But here we deal with numeric values and Integer objects. Also, one of the variables, i4, is initialized using a number of command line arguments supplied to the program, which is definitely a run-time information. Yet, == still finds it equal to i3.
So, given all the above, how exactly is the equality operator supposed to work in Java? Does it, or does it not, inspect the objects' contents when comparing them?
Thanks!
Integer objects are cached as mentioned by the Javadocs of Integer#valueOf(int):
This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
The statement Integer i4 = (args.length + 1) * 6; calls Integer#valueOf(int) which returns the cached instance. On the other hand, if you use Integer i4 = new Integer((args.length + 1) * 6);, the reference equality will return false.
I think the example shows us how java int pool is working. So in the i4 case if you provided no arguments on runtime the result is 6. Now the int pool kicks in and uses the i1 value which is part of the -128 to to 127 int pool. So on an object level they really equal and that's what == is all about.
When you autobox an int, you're internally calling Integer.valueOf(int), which according to the documentation may return cached values. So it makes perfect sense that you're seeing reference equality.
More generally, you should never assume two references are distinct unless you explicitly constructed them. And for the record, string interning is available at runtime as well, through the String.intern() method.

Categories