Any chance of Object auto casting to Integer? - java

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.

Related

Use int or Integer

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

Differences between new Integer(123), Integer.valueOf(123) and just 123

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

Why do people still use primitive types in Java?

Since Java 5, we've had boxing/unboxing of primitive types so that int is wrapped to be java.lang.Integer, and so and and so forth.
I see a lot of new Java projects lately (that definitely require a JRE of at least version 5, if not 6) that are using int rather than java.lang.Integer, though it's much more convenient to use the latter, as it has a few helper methods for converting to long values et al.
Why do some still use primitive types in Java? Is there any tangible benefit?
In Joshua Bloch's Effective Java, Item 5: "Avoid creating unnecessary objects", he posts the following code example:
public static void main(String[] args) {
Long sum = 0L; // uses Long, not long
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i;
}
System.out.println(sum);
}
and it takes 43 seconds to run. Taking the Long into the primitive brings it down to 6.8 seconds... If that's any indication why we use primitives.
The lack of native value equality is also a concern (.equals() is fairly verbose compared to ==)
for biziclop:
class Biziclop {
public static void main(String[] args) {
System.out.println(new Integer(5) == new Integer(5));
System.out.println(new Integer(500) == new Integer(500));
System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
}
}
Results in:
false
false
true
false
EDIT Why does (3) return true and (4) return false?
Because they are two different objects. The 256 integers closest to zero [-128; 127] are cached by the JVM, so they return the same object for those. Beyond that range, though, they aren't cached, so a new object is created. To make things more complicated, the JLS demands that at least 256 flyweights be cached. JVM implementers may add more if they desire, meaning this could run on a system where the nearest 1024 are cached and all of them return true... #awkward
Autounboxing can lead to hard to spot NPEs
Integer in = null;
...
...
int i = in; // NPE at runtime
In most situations the null assignment to in is a lot less obvious than above.
Boxed types have poorer performance and require more memory.
Primitive types:
int x = 1000;
int y = 1000;
Now evaluate:
x == y
It's true. Hardly surprising. Now try the boxed types:
Integer x = 1000;
Integer y = 1000;
Now evaluate:
x == y
It's false. Probably. Depends on the runtime. Is that reason enough?
Besides performance and memory issues, I'd like to come up with another issue: The List interface would be broken without int.
The problem is the overloaded remove() method (remove(int) vs. remove(Object)). remove(Integer) would always resolve to calling the latter, so you could not remove an element by index.
On the other hand, there is a pitfall when trying to add and remove an int:
final int i = 42;
final List<Integer> list = new ArrayList<Integer>();
list.add(i); // add(Object)
list.remove(i); // remove(int) - Ouch!
Can you really imagine a
for (int i=0; i<10000; i++) {
do something
}
loop with java.lang.Integer instead? A java.lang.Integer is immutable, so each increment round the loop would create a new java object on the heap, rather than just increment the int on the stack with a single JVM instruction. The performance would be diabolical.
I would really disagree that it's much mode convenient to use java.lang.Integer than int. On the contrary. Autoboxing means that you can use int where you would otherwise be forced to use Integer, and the java compiler takes care of inserting the code to create the new Integer object for you. Autoboxing is all about allowing you to use an int where an Integer is expected, with the compiler inserting the relevant object construction. It in no way removes or reduces the need for the int in the first place. With autoboxing you get the best of both worlds. You get an Integer created for you automatically when you need a heap based java object, and you get the speed and efficiency of an int when you are just doing arithmetic and local calculations.
Primitive types are much faster:
int i;
i++;
Integer (all Numbers and also a String) is an immutable type: once created it can not be changed. If i was Integer, than i++ would create a new Integer object - much more expensive in terms of memory and processor.
First and foremost, habit. If you've coded in Java for eight years, you accumulate a considerable amount of inertia. Why change if there is no compelling reason to do so? It's not as if using boxed primitives comes with any extra advantages.
The other reason is to assert that null is not a valid option. It would be pointless and misleading to declare the sum of two numbers or a loop variable as Integer.
There's the performance aspect of it too, while the performance difference isn't critical in many cases (though when it is, it's pretty bad), nobody likes to write code that could be written just as easily in a faster way we're already used to.
By the way, Smalltalk has only objects (no primitives), and yet they had optimized their small integers (using not all 32 bits, only 27 or such) to not allocate any heap space, but simply use a special bit pattern. Also other common objects (true, false, null) had special bit patterns here.
So, at least on 64-bit JVMs (with a 64 bit pointer namespace) it should be possible to not have any objects of Integer, Character, Byte, Short, Boolean, Float (and small Long) at all (apart from these created by explicit new ...()), only special bit patterns, which could be manipulated by the normal operators quite efficiently.
I can't believe no one has mentioned what I think is the most important reason:
"int" is so, so much easier to type than "Integer". I think people underestimate the importance of a concise syntax. Performance isn't really a reason to avoid them because most of the time when one is using numbers is in loop indexes, and incrementing and comparing those costs nothing in any non-trivial loop (whether you're using int or Integer).
The other given reason was that you can get NPEs but that's extremely easy to avoid with boxed types (and it is guaranteed to be avoided as long as you always initialize them to non-null values).
The other reason was that (new Long(1000))==(new Long(1000)) is false, but that's just another way of saying that ".equals" has no syntactic support for boxed types (unlike the operators <, >, =, etc), so we come back to the "simpler syntax" reason.
I think Steve Yegge's non-primitive loop example illustrates my point very well:
http://sites.google.com/site/steveyegge2/language-trickery-and-ejb
Think about this: how often do you use function types in languages that have good syntax for them (like any functional language, python, ruby, and even C) compared to java where you have to simulate them using interfaces such as Runnable and Callable and nameless classes.
Couple of reasons not to get rid of primitives:
Backwards compatability.
If it's eliminated, any old programs wouldn't even run.
JVM rewrite.
The entire JVM would have to be rewritten to support this new thing.
Larger memory footprint.
You'd need to store the value and the reference, which uses more memory. If you have a huge array of bytes, using byte's is significantly smaller than using Byte's.
Null pointer issues.
Declaring int i then doing stuff with i would result in no issues, but declaring Integer i and then doing the same would result in an NPE.
Equality issues.
Consider this code:
Integer i1 = 5;
Integer i2 = 5;
i1 == i2; // Currently would be false.
Would be false. Operators would have to be overloaded, and that would result in a major rewrite of stuff.
Slow
Object wrappers are significantly slower than their primitive counterparts.
Objects are much more heavyweight than primitive types, so primitive types are much more efficient than instances of wrapper classes.
Primitive types are very simple: for example an int is 32 bits and takes up exactly 32 bits in memory, and can be manipulated directly. An Integer object is a complete object, which (like any object) has to be stored on the heap, and can only be accessed via a reference (pointer) to it. It most likely also takes up more than 32 bits (4 bytes) of memory.
That said, the fact that Java has a distinction between primitive and non-primitive types is also a sign of age of the Java programming language. Newer programming languages don't have this distinction; the compiler of such a language is smart enough to figure out by itself if you're using simple values or more complex objects.
For example, in Scala there are no primitive types; there is a class Int for integers, and an Int is a real object (that you can methods on etc.). When the compiler compiles your code, it uses primitive ints behind the scenes, so using an Int is just as efficient as using a primitive int in Java.
In addition to what others have said, primitive local variables are not allocated from the heap, but instead on the stack. But objects are allocated from the heap and thus have to be garbage collected.
It's hard to know what kind of optimizations are going on under the covers.
For local use, when the compiler has enough information to make optimizations excluding the possibility of the null value, I expect the performance to be the same or similar.
However, arrays of primitives are apparently very different from collections of boxed primitives. This makes sense given that very few optimizations are possible deep within a collection.
Furthermore, Integer has a much higher logical overhead as compared with int: now you have to worry about about whether or not int a = b + c; throws an exception.
I'd use the primitives as much as possible and rely on the factory methods and autoboxing to give me the more semantically powerful boxed types when they are needed.
int loops = 100000000;
long start = System.currentTimeMillis();
for (Long l = new Long(0); l<loops;l++) {
//System.out.println("Long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around Long: "+ (System.currentTimeMillis()- start));
start = System.currentTimeMillis();
for (long l = 0; l<loops;l++) {
//System.out.println("long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around long: "+ (System.currentTimeMillis()- start));
Milliseconds taken to loop '100000000' times around Long: 468
Milliseconds taken to loop '100000000' times around long: 31
On a side note, I wouldn't mind seeing something like this find it's way into Java.
Integer loop1 = new Integer(0);
for (loop1.lessThan(1000)) {
...
}
Where the for loop automatically increments loop1 from 0 to 1000
or
Integer loop1 = new Integer(1000);
for (loop1.greaterThan(0)) {
...
}
Where the for loop automatically decrements loop1 1000 to 0.
Primitive types have many advantages:
Simpler code to write
Performance is better since you are not instantiating an object for the variable
Since they do not represent a reference to an object there is no need to check for nulls
Use primitive types unless you need to take advantage of the boxing features.
You need primitives for doing mathematical operations
Primitives takes less memory as answered above and better performing
You should ask why Class/Object type is required
Reason for having Object type is to make our life easier when we deal with Collections. Primitives cannot be added directly to List/Map rather you need to write a wrapper class. Readymade Integer kind of Classes helps you here plus it has many utility methods like Integer.pareseInt(str)
I agree with previous answers, using primitives wrapper objects can be expensive.
But, if performance is not critical in your application, you avoid overflows when using objects. For example:
long bigNumber = Integer.MAX_VALUE + 2;
The value of bigNumber is -2147483647, and you would expect it to be 2147483649. It's a bug in the code that would be fixed by doing:
long bigNumber = Integer.MAX_VALUE + 2l; // note that '2' is a long now (it is '2L').
And bigNumber would be 2147483649. These kind of bugs sometimes are easy to be missed and can lead to unknown behavior or vulnerabilities (see CWE-190).
If you use wrapper objects, the equivalent code won't compile.
Long bigNumber = Integer.MAX_VALUE + 2; // Not compiling
So it's easier to stop these kind of issues by using primitives wrapper objects.
Your question is so answered already, that I reply just to add a little bit more information not mentioned before.
Because JAVA performs all mathematical operations in primitive types. Consider this example:
public static int sumEven(List<Integer> li) {
int sum = 0;
for (Integer i: li)
if (i % 2 == 0)
sum += i;
return sum;
}
Here, reminder and unary plus operations can not be applied on Integer(Reference) type, compiler performs unboxing and do the operations.
So, make sure how many autoboxing and unboxing operations happen in java program. Since, It takes time to perform this operations.
Generally, it is better to keep arguments of type Reference and result of primitive type.
The primitive types are much faster and require much less memory. Therefore, we might want to prefer using them.
On the other hand, current Java language specification doesn’t allow usage of primitive types in the parameterized types (generics), in the Java collections or the Reflection API.
When our application needs collections with a big number of elements, we should consider using arrays with as more “economical” type as possible.
*For detailed info see the source: https://www.baeldung.com/java-primitives-vs-objects
To be brief: primitive types are faster and require less memory than boxed ones

Why aren't Integers cached in Java?

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.

Comparing Character, Integer and similar types in Java: Use equals or ==?

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.

Categories

Resources