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).
Related
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.
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.
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.
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.
What is an elegant, readable and non-verbose way of comparing two floating point value for exact equality?
As simple as it may sound, its a wicked problem. The == operator doesn't get the job done for NaN and also has special treatment for zero:
(+0.0 == -0.0) -> true
Double.NaN == Double.NaN -> false
But I want to determine if two values are exactly the same (but I do not care for different NaN patterns, so any NaN == any other NaN -> true).
I can do this with this ugly Monster piece of code:
Double.doubleToLongBits(a) == Double.doubleToLongBits(b)
Is there a better way to write this (and make the intent obvious)?
You can use
Double.compare(a, b) == 0
From the javadoc for compareTo
Double.NaN is considered by this method to be equal to itself and greater than all other double values (including Double.POSITIVE_INFINITY).
0.0d is considered by this method to be greater than -0.0d.
What you've got is already the best way of doing it, I'd say. It makes it clear that you're interested in the bitwise representation of the value. You happen to be converting those bits to long as a convenient 64-bit type which doesn't have any funky behaviour.
If you don't want it appearing frequently in your codebase, just add a method to wrap it:
public static boolean bitwiseEqualsWithCanonicalNaN(double x, double y) {
return Double.doubleToLongBits(x) == Double.doubleToLongBits(y);
}
Note that as per your question, this does not differentiate between different NaN values. If you wanted to do this at a later date, you'd need to use Double.toRawLongBits.