I know there are similar posts on the topic, but they don't quite address my question. When you do:
Integer a = 10;
Integer b = 10;
System.out.println("a == b: " + (a == b));
This will (apparently) print true most of the time because integers in the range [-128, 127] are somehow cached. But:
Integer a = new Integer(10);
Integer b = new Integer(10);
System.out.println("a == b: " + (a == b));
Will return false. I understand that I am asking for new instances of an Integer, but since boxed primitives are immutable in Java, and the machinery is already there to do the "right thing" (as seen in the first case), why does this happen?
Wouldn't it make more sense if all instances of an Integer with a 10 be the same object in memory? In other words, why don't we have "Integer interning" which would be similar to "String interning"?
Better yet, wouldn't it make more sense if instances of a boxed primitive representing the same thing, regardless of value (and type), be the same object ? Or at least respond correctly to ==?
It should be very clear that caching has an unacceptable performance hit -- an extra if statement and memory lookup every time you create an Integer. That alone overshadows any other reason and the rest of the agonizing on this thread.
As far as responding "correctly" to ==, the OP is mistaken in his assumption of correctness. Integers DO respond correctly to == by the general Java community's expectation of correctness and of course by the specification's definition of correctness. That is, if two references point to the same object, they are ==. If two references point to different objects, they are not == even if they have the same contents. Thus, it should be no surprise that new Integer(5) == new Integer(5) evaluates to false.
The more interesting question is why new Object(); should be required to create a unique instance every time? i. e. why is new Object(); not allowed to cache? The answer is the wait(...) and notify(...) calls. Caching new Object()s would incorrectly cause threads to synchronize with each other when they shouldn't.
If it were not for that, then Java implementations could totally cache new Object()s with a singleton.
And that should explain why new Integer(5) done 7 times must be required to create 7 unique Integer objects each containing the value 5 (because Integer extends Object).
Secondary, Less Important Stuff: One problem in this otherwise nice scheme results from the autoboxing and autounboxing feature. Without the feature you could not do comparisons such as new Integer(5) == 5. To enable these, Java unboxes the object (and does not box the primitive). Therefore new Integer(5) == 5 is converted to: new Integer(5).intValue() == 5 (and not new Integer(5) == new Integer(5).
One last thing to understand is that autoboxing of n is not done by new Integer(n). It is done internally by a call to Integer.valueOf(n).
If you think you understand and want to test yourself, predict the output of the following program:
public class Foo {
public static void main (String[] args) {
System.out.println(Integer.valueOf(5000) == Integer.valueOf(5000));
System.out.println(Integer.valueOf(5000) == new Integer(5000));
System.out.println(Integer.valueOf(5000) == 5000);
System.out.println(new Integer(5000) == Integer.valueOf(5000));
System.out.println(new Integer(5000) == new Integer(5000));
System.out.println(new Integer(5000) == 5000);
System.out.println(5000 == Integer.valueOf(5000));
System.out.println(5000 == new Integer(5000));
System.out.println(5000 == 5000);
System.out.println("=====");
System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
System.out.println(Integer.valueOf(5) == new Integer(5));
System.out.println(Integer.valueOf(5) == 5);
System.out.println(new Integer(5) == Integer.valueOf(5));
System.out.println(new Integer(5) == new Integer(5));
System.out.println(new Integer(5) == 5);
System.out.println(5 == Integer.valueOf(5));
System.out.println(5 == new Integer(5));
System.out.println(5 == 5);
System.out.println("=====");
test(5000, 5000);
test(5, 5);
}
public static void test (Integer a, Integer b) {
System.out.println(a == b);
}
}
For extra credit, also predict the output if all the == are changed to .equals(...)
Update: Thanks to comment from user #sactiw : "default range of cache is -128 to 127 and java 1.6 onward you can reset the upper value >=127 by passing -XX:AutoBoxCacheMax= from command line"
This would potentially break code written before this design change, when everybody righfully assumed that two newly created instances were different instances. It could be done for autoboxing, because autoboxing didn't exist before, but changing the meaning of new is too dangerous, and probably doesn't bring much gain. The cost of short-lived objects is not big in Java, and could even be lower than the cost of maintaining a cache of long-lived objects.
If you check the source you see:
/**
* Returns an Integer instance representing the specified int value. If a new
* Integer instance is not required, this method should generally be used in
* preference to the constructor Integer(int), as this method is likely to
* yield significantly better space and time performance by caching frequently
* requested values.
*
* #Parameters: i an int value.
* #Returns: an Integer instance representing i.
* #Since: 1.5
*/
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
Source: link
It's the performance reasons why == returns boolean true with integers - it is totally a hack. If you want to compare values, then for that you have compareto or equals method.
In other languages, for example you can use == to compare strings as well, it is basically the same reason and it is called as one of the biggest mishaps of java language.
int is a primitive type, predefined by the language and named by a reserved keyword. As a primitive it does not contain class or any class associated information. Integer is an immutable primitive class, that is loaded through a package-private, native mechanism and casted to be Class - this provides auto boxing and was introduced in JDK1.5. Prior JDK1.5 int and Integer where 2 very different things.
In Java, every time you call the new operator, you allocate new memory and you create a new object. That's standard language behavior, and to my knowledge there is no way to bypass this behavior. Even standard classes have to abide by this rule.
It is my understanding that new will create a new object, no matter what. The order of operations here is that you first call new, which instantiates a new object, then the constructor gets called. There is no place for the JVM to intervene and turn the new into a "grab a cached Integer object based on the value passed into the constructor".
Btw, have you considered Integer.valueOf? That works.
Wouldn't it make more sense if all instances of an Integer with a 10 be the same object in memory? In other words, why don't we have "Integer interning" which is similar to "String interning"?
Because it would be awful!
First, this code would throw an OutOfMemoryError:
for (int i = 0; i <= Integer.MAX_VALUE; i++) {
System.out.printf("%d\n", i);
}
Most Integer objects are probably short-lived.
Second, how would you maintain such a set of canonical Integer objects? With some kind of table or map. And how would you arbitrate access to that map? With some kind of locking. So suddenly autoboxing would become a performance-killing synchronization nightmare for threaded code.
Your first example is a byproduct of the spec requiring that flyweights be created in a certain range around 0. It should never, ever, be relied on.
As for why Integer doesn't work like String ? I would imagine avoiding overhead to an already slow process. The reason you use primitives where you can is because they are significantly faster and take up way less memory.
Changing it now could break existing code because you're changing the functionality of the == operator.
BTW, If you do
Integer a = 234345;
Integer b = 234345;
if (a == b) {}
it is possible that this will be true.
This is because since you didn't use new Integer(), the JVM (not the class code) is allowed to cache its own copies of Integers if it sees fit. Now you shouldn't write code based on this, but when you say new Integer(234345) you are guaranteed by the spec that you will definitely have different objects.
new means new.
new Object() isn't frivolous.
A new instance is a new instance, so they are equal in value, but they are not equal as objects.
So a == b can't return true.
If they were 1 object, as you ask for: a+=2; would add 2 to all int = 10 - that would be awful.
Let me just expand slightly on ChrisJ's and EboMike's answers by giving links to the relevant sections of the JLS.
new is a keyword in Java, allowed in class instance creation expressions (Section 15.9 of the JLS). This is different from C++, where new is an operator and can be overloaded.
The expression always tries to allocate memory, and yields a fresh object each time it is evaluated (Section 15.9.4). So at that point it's already too late for cache lookup.
Assuming your describing the behavior of you code accurately it sounds like autoboxing isn't working on the 'gets' (=) operatior, instead it sounds like Integer x = 10; gives the object x a memory pointer of '10' instead of a vale of 10. Therefore ((a == b) == true)( will evaluate to true because == on objects operates on the memory addresses which you assigned both to 10.
So when should you use autoboxing and unboxing? Use them only when there is an “impedance mismatch” between reference types and primitives, for example, when you have to put numerical values into a collection. It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code. An Integer is not a substitute for an int; autoboxing and unboxing blur the distinction between primitive types and reference types, but they do not eliminate it.
What oracle has to say on the subject.
Notice that the documentation doesn't supply any examples with the '=' operator.
For Integer objects use the a.equals(b) condition to compare.
The compiler will not do the unboxing for you while you compare, unless you assign the value to a basic type.
Please also note that the cache range was -128 to 127 in Java 1.5 but Java 1.6 onward it is the default range i.e. you can set upper value >= 127 by passing -XX:AutoBoxCacheMax=new_limit from command line
It's because you're using the new statement to construct the objetcs.
Integer a = Integer.valueOf(10);
Integer b = Integer.valueOf(10);
System.out.println("a == b: " + (a == b));
That will print out true. Weird, but Java.
Related
I am wondering whether the below code should work in any scenario?
Object value = attValue.getValue(); // Returns an Object, might contain an Integer
if (value instanceof Integer) {
if (mAccount.getValue() != value) { // mAccount.getValue() return int
// Do something here
}
}
It works in my Android studio but not in some other's PC. What is making it work for me?
Yes, that's entirely feasible given the way autoboxing is guaranteed to work on small values, and is permitted to work on larger values. For example, this is guaranteed to print true:
Object x = 5;
Object y = 5;
System.out.println(x == y);
This might print true, but isn't guaranteed to:
Object x = 10000;
Object y = 10000;
System.out.println(x == y);
I would definitely try not to rely on this in code though, partly because while values in the range of -128 to 127 inclusive are guaranteed to be reused (see JLS 5.1.7), the fact that some JVMs may reuse a wider range of values could lead you into a false sense of security about your code.
In your case, we don't know whether you're seeing a difference in platforms (also bearing in mind that we're talking about Android rather than a JVM) or just that when it "worked" the value being boxed was small, and when it "didn't work" it wasn't.
You're getting the same Integer instance, since Java 5 there has been an Integer Cache. Because of that cache, you get the same Integer reference (you're getting the same Integer reference, and because it's the same reference they have reference identity - which is what == tests). The linked Integer cache document says (in part)
Integer objects are cached internally and reused via the same referenced objects.
This is applicable for Integer values in range between –127 to +127 (Max Integer value).
This Integer caching works only on autoboxing. Integer objects will not be cached when they are built using the constructor.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Using == operator in Java to compare wrapper objects
java version 1.6.0_26
From a book for SCJP exam preparation:
In order to save memory, two instance of the following[Short and Integer from -128 and 127, and some other but doesn't matter for question] wrapper objects (created throught boixng), will always be == when their primitive values are the same.
What I did:
If we will compare two integer from -128 to 127 like this:
1. Integer i1 = 10;
2. Integer i2 = 10;
3. System.out.println(i1 == i2); // true
But why the same give us "false" or may be it's not the same things:
4. Integer i3 = new Integer(10);
5. Integer i4 = new Integer(10);
6. System.out.println(i3 == i4); // false
My questions:
1) Does on the 1st line of code we make implicit boxing?
2) Why the 3rd and 6th lines of code give us different results?
Does on the 1st line of code we make implicit boxing?
Yes
2) Why the 3rd and 6th lines of code give us different results?
Integer.valueOf(int) pools all values from -128 to 127.
The reason is that small Integer values are used frequently and there is no point in creating a new object for all such values everytime we need an object. Hence, these are created as "interned" objects and all the references to such integer values will point to the same memory address.
code snippet from Integer.java:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
Instead, when you call new Integer(10);, it is making an entire new object hence two different objects with same integer values will point to different memory addresses
1) Does on the 1st line of code we make implicit boxing?
Yes. Its called Auto-Boxing
2) Why the 3rd and 6th lines of code give us different results?
The == actually checks whether two variables are having exactly same value. Note that a primitive variable contain what you see, but a reference variable contain the address to the object that it holds.
When == is used to compare a primitive to a wrapper, the wrapper will be unwrapped and the comparison will be primitive to primitive, and hence it will be true always as it is a primitive comparison and not object comparison. So that's why
System.out.println(i1 == i2);
Will be true.
But in line 6.
System.out.println(i3 == i4);
You are comparing two objects unless the objects have the same reference it will not be true. If you use .equals method you can get true. Try
System.out.println(i3.equals(i4));
In your first example, the compiler is using boxing to assign the variables. In this case, i1/i2 are constants (a bit like static final objects).
In the second example, you create two instances of an Integer, hence they are never the same.
The 6 line is showing false because it is comparing to see if the references i3 and i4 are pointing to the same object! In this case it is not. hence the false.
Autoboxing and UnBoxing comes into picture if there are both wrappers and Primitives involved. Here both i3 and i4 are wrapper objects, Hence it will be treated as any other POJO
AutoBoxing happens only if there are both wrapper objects and a primitives involved,
for example
int primitive = 10;
Integer wrapper = new Integer(10);
System.out.println(primitive == wrapper); //true
prints True in the above == comparison the value of the primitive is compared with the state of the wrapper.
In my code there are a lot of final values, like 10000. They never change, i do nothing with them, just sometimes checks like if(number1 == number2).
Is it better to use int or Integer for such numbers?
In your case, use int.
In a general case, if you're in the situation where you could feasibly use either the primitive value is almost always preferred:
They're potentially more memory efficient
You can always use == reliably, which isn't the case with the class Integer type - you'd have to use .equals() to ensure you were getting what you wanted. See here for more details.
Memory requirements are a lot less of an issue these days, but the big gotcha is the second one, which can cause the potential for a lot of bugs if you're not aware of it (especially since there's cases where == will work as you expect, and others where it won't - it's not a "reliable" bug in that sense.)
Since Integers are objects, they take up more space in memory. If you don't ever use Integer methods or anything else requiring it to be an object, ints are more memory-efficient, since int is a primitive type.
In the grand scheme of things, it probably won't matter given how much memory modern computers have. No harm being safe though.
I should note that if you're using == for Integers, you're checking if the references are the same. For Integer objects, the equals() method will be preferred.
use int, as it is the primitive type. It is always a better option because of memory efficiency to choose a primitive type instead of choosing a full fledged wrapper object.
You are comparing references so its better to use int.
Never use "==" to compare Integer objects (or Float, Double, Short, Character, Byte, Long, BigDecimal...) for equality. Compare numbers in their primitive form -- i.e., work with int, short, long, double.
If you want to compare Integers use method compareTo().
It doesn't really matter if it's int or Integer. In java, they're very interchangeable by the use of autoboxing.
It does however make a difference if you plan to store them in a collection. Collections only accept objects, which means you'll have to use Integer.
If you decide to use Integer and want to compare them, don't use ==. Instead, use the compareTo method or the equals method.
For constants use int, as with constants you only need to be able to get their value. Everything else that comes with Integer is redundant in this case.
Where you need to pass integers as parameters, it's handy to use Integer as you get one more option of the parameter value being null (i.e. a case with an invalid parameter, or a legit no-value case).
Use int when you can and use Integer when you must:
If the values can be null use Integer but you will have to use the methods compareTo and Equals to make comparison between then.
If your value can't be null, useint, that way you will have a more readable code with the classical operators ==, >=, <, etc...
// int primitive, easy to handle
int a = 5;
int b = 5;
int c = null; // Compile error, can't have null primitive values
if(a == b) // True
if(a > b) // False
if(a >= b) // True
// Integer, more complicated:
Integer A = new Integer(5);
Integer B = new Integer(5);
Integer c = null; // Work
if(A == B) // False, they are not the same objects
if(A.equals(B)) // True, same value
if(A > B) // Compile error...
if(A.compareTo(B)>0) // A > B, the int version is more readable
if(A.compareTo(B)>=0) // A >= B, the int version is more readable
Recenlty I saw code (Java) like this:
myMethod(new Integer(123));
I am currently refactoring some code, and there is a tip in Sonar tool, that it's more memory friendly to use sth like this:
myMethod(Integer.valueOf(123));
However in this case, I think that there is no difference if I would use:
myMethod(123);
I could understand that, if I would pass a variable to the method, but hard coded int? Or if there would be Long/Double etc and I want Long representation of number. But integer?
new Integer(123) will create a new Object instance for each call.
According to the javadoc, Integer.valueOf(123) has the difference it caches Objects... so you may (or may not) end up with the same Object if you call it more than once.
For instance, the following code:
public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println("a==b? " + (a==b));
Integer c = Integer.valueOf(1);
Integer d = Integer.valueOf(1);
System.out.println("c==d? " + (c==d));
}
Has the following output:
a==b? false
c==d? true
As to using the int value, you are using the primitive type (considering your method also uses the primitive type on its signature) - it will use slightly less memory and might be faster, but you won't be ale to add it to collections, for instance.
Also take a look at Java's AutoBoxing if your method's signature uses Integer- when using it, the JVM will automatically call Integer.valueOf() for you (therefore using the cache aswell).
public static Integer valueOf(int i)
Returns a Integer instance representing the specified int value. If a new Integer instance is not required, this method should
generally be used in preference to the constructor Integer(int), as
this method is likely to yield significantly better space and time
performance by caching frequently requested values.
Parameters:
i - an int value.
Returns:
a Integer instance representing i.
Since:
1.5
refer http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Integer.html#valueOf%28int%29
This variant of valueOf was added in JDK 5 to Byte, Short, Integer, and Long (it already existed in the trivial case in Boolean since JDK 1.4). All of these are, of course, immutable objects in Java. Used to be that if you needed an Integer object from an int, you’d construct a new Integer. But in JDK 5+, you should really use valueOf because Integer now caches Integer objects between -128 and 127 and can hand you back the same exact Integer(0) object every time instead of wasting an object construction on a brand new identical Integer object.
private static class IntegerCache {
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
refer Why YOU should use Integer.valueOf(int)
EDIT
autoboxing and object creation:
The important point we must consider is that autoboxing doesn't reduce object creation, but it reduces code complexity. A good rule of thumb is to use primitive types where there is no need for objects, for two reasons:
Primitive types will not be slower than their corresponding wrapper types, and may be a lot faster.
There can be some unexpected behavior involving == (compare references) and .equals() (compare values).
Normally, when the primitive types are boxed into the wrapper types, the JVM allocates memory and creates a new object. But for some special cases, the JVM reuses the same object.
The following is the list of primitives stored as immutable objects:
boolean values true and false
All byte values
short values between -128 and 127
int values between -128 and 127
char in the range \u0000 to \u007F
refer http://today.java.net/pub/a/today/2005/03/24/autoboxing.html#performance_issue
only range between -128 to +127 implements in cache.
Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println("a==b? " + (a==b));
Integer c = Integer.valueOf(127);
Integer d = Integer.valueOf(127);
System.out.println("c==d? " + (c==d));
Integer e = Integer.valueOf(128);
Integer f = Integer.valueOf(128);
System.out.println("e==f? " + (e==f));
Refer this java specification:
http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7
in JDK 5+, you should really use valueOf because Integer now caches Integer objects between -128 and 127 and can hand you back the same exact Integer(0) object every time instead of wasting an object construction on a brand new identical Integer object.
int is primitive type, not an object.
new Integer(123) and Integer.valueOf(123) both return Integer object representing value 123. As per javadoc for Integer.valueOf():
Returns a Integer instance representing the specified int value.
If a new Integer instance is not required, this method should generally
be used in preference to the constructor Integer(int), as this method is
likely to yield significantly better space and time performance by caching
frequently requested values.
Does your method require an int or an Integer?
new Integer(int) and Integer.valueOf(int) both return Integer objects, but valueOf should be preferred as it is more efficient because it returns cached objects. If your method requires an Integer you should use Integer.valueOf.
If your method requires an int, you should use an int (e.g. 123).
However, it is not strictly necessary to match types in this way because of autoboxing, which automatically converts an int to an Integer and vice versa when the types don't match. This allows you to pass an int into a method requiring an Integer, and an Integer into a method requiring an int. But be aware that there are performance costs associated with autoboxing. The most common example of when you would use autoboxing is if you wanted to store primitives in a collection.
When you use some thing like new Integer(88) the SpotBugs code analyze tool, complains a performance issue.
The description of this issue shows deference of new and valueOf
Method invokes inefficient Number constructor; use static valueOf
instead Using new Integer(int) is guaranteed to always result in a new
object whereas Integer.valueOf(int) allows caching of values to be
done by the compiler, class library, or JVM. Using of cached values
avoids object allocation and the code will be faster. Values between
-128 and 127 are guaranteed to have corresponding cached instances and using valueOf is approximately 3.5 times faster than using
constructor. For values outside the constant range the performance of
both styles is the same. Unless the class must be compatible with JVMs
predating Java 5, use either autoboxing or the valueOf() method when
creating instances of Long, Integer, Short, Character, and Byte. Bug
kind and pattern: Bx - DM_NUMBER_CTOR
I wanted to make sure about something in Java:
If I have a Character or an Integer or a Long and those sort of things, should I use equals or is == sufficient?
I know that with strings there are no guarantees that there is only one instance of each unique string, but I'm not sure about other boxed types.
My intuition is to use equals, but I want to make sure I'm not wasting performance.
EDIT: The spec makes some guarantees for boxing conversions. From section 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.
The implementation can use a larger pool, mind you.
I would really avoid writing code which relies on that though. Not because it might fail, but because it's not obvious - few people will know the spec that well. (I previously thought it was implementation-dependent.)
You should use equals or compare the underlying values, i.e.
if (foo.equals(bar))
or
if (foo.intValue() == bar.intValue())
Note that even if the autoboxing were guaranteed to use fixed values, other callers can always create separate instances anyway.
If you want to compare anything about the value of any object, use .equals().
Even (and especially) if those Objects are the primitive wrapper types Byte, Character, Short, Integer, Long, Float, Double and Boolean.
"==" only ever compares the object identity and you that's very, very rarely what you want. And de-facto never what you want with the primitive wrappers.
Only use == in one of those two scenarios:
all values involved in the comparison are primitive types (and preferably not floating point numbers)
you really want to know if two references refer to the same object (this includes comparison of enums, because there the value is bound to the object identity)
Java Language Spec 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.
and:
Discussion
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 characters and shorts, as
well as integers and longs in the
range of -32K - +32K.
So, in some cases == will work, in many others it will not. Always use .equals to be safe since you cannot grantee (generally) how the instances were obtained.
If speed is a factor (most .equals start with an == comparison, or at least they should) AND you can gurantee how they were allocated AND they fit in the above ranges then == is safe.
Some VMs may increase that size, but it is safer to assume the smallest size as specified by the langauge spec than to rely on a particular VM behaviour, unless you really really really need to.
//Quick test
public class Test {
public static void main(String[] args) {
System.out.println("Are they equal? "+ (new Long(5) == new Long(5)));
}
}
Output:
"Are they equal? 0"
Answer:
No, they're not equal. You must use .equals or compare their primitive values.
Implementations of the equals(Object o) method almost always start with
if(this == o) return true;
so using equals even if == is true is really not much of a performance hit.
I recommend always* using the equals method on objects.
* of course there are a very few times when you should not take this advice.
The general answer is no, you are not guaranteed that for the same numeric value, the Long objects you get are the same (even if you restrict yourself to using Long.valueOf()).
However, it is possible that you would get a performance improvement by first trying to test the equality of references (using ==) and then, if failed, trying equals(). It all hinges on the comparative costs of the additional == test and the method call... Your mileage may vary, but it is worth trying a simple loop test to see which is better.
It is worth noting that auto-boxed values will uses pooled object if they are available. This is why (Integer) 0 == (Integer) 0 but (Integer) 128 != (Integer) 128 for Java 6u13
I like to see the result visually:
public static void main(String[] args)
{
Integer a = 126; //no boxed up conversion, new object ref
Integer b = 126; //no boxed up conversion, re-use memory address
System.out.println("Are they equal? " + (a == b)); // true
Integer a1 = 140; //boxed up conversion, new object
Integer b1 = 140; //boxed up conversion, new object
System.out.println("Are they equal? " + (a1 == b1)); // false
System.out.println("Are they equal? " + (new Long(5) == new Long(5))); // false
}
== compares the object reference while equals(Object obj) compares for object equality. If there can ever be more than one instance of an equals object in existence then you must use equals for equality comparison.
Examples:
Integer i1 = new Integer(12345);
Integer i2 = new Integer(12345);
these are different object instances but are equal according to Integer's equality, so you must use equals(Object obj)
public enum Gender {
MALE, FEMALE;
}
in this case there will only be one instance of FEMALE in existence so == is safe to use.