This site is the archived OWASP Foundation Wiki and is no longer accepting Account Requests.
To view the new OWASP Foundation website, please visit https://owasp.org
Difference between revisions of "Java gotchas"
(Added link to JLS 5.1.7) |
Adam Boulton (talk | contribs) (→Integer Caching) |
||
Line 12: | Line 12: | ||
But they do contain the same value | But they do contain the same value | ||
These two are the same, because they use the same reference. | These two are the same, because they use the same reference. | ||
− | === | + | === Integer Caching=== |
− | Java 5 | + | Since Java 5 Integer caching was introduced. When creating an Integer using the following code: |
+ | |||
+ | Integer myNumber = 10 | ||
+ | Or | ||
+ | Integer myNumber = Integer.valueOf(10); | ||
+ | |||
+ | 256 Integer objects are created in the range of -128 to 127 which are all stored in an Integer array. This caching functionality can be seen by looking at the inner class, IntegerCache, which is found in Integer: | ||
+ | |||
+ | <pre> | ||
+ | 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); | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | So when creating an object using Integer.valueOf or directly assigning a value to an Integer within the range of -128 to 127 the same object will be returned. Therefore, consider the following example: | ||
+ | |||
Integer i = 100; | Integer i = 100; | ||
Integer p = 100; | Integer p = 100; | ||
Line 19: | Line 53: | ||
if (i != p) System.out.println("i and p are different."); | if (i != p) System.out.println("i and p are different."); | ||
if(i.equals(p)) System.out.println("i and p contain the same value."); | if(i.equals(p)) System.out.println("i and p contain the same value."); | ||
− | The output is: | + | |
+ | The output is: | ||
i and p are the same. | i and p are the same. | ||
i and p contain the same value. | i and p contain the same value. | ||
+ | |||
+ | It is important to note that object i and p only equate to true because they are the same object, the comparison is not based on the value, it is based on object equality. If Integer i and p are outside the range of -128 or 127 the cache is not used, therefore new objects are created. When doing a comparison for value always use the “.equals” method. It is also important to note that instantiating an Integer does not create this caching. So consider the following example: | ||
+ | |||
+ | Integer i = new Integer (100); | ||
+ | Integer p = new Integer(100); | ||
+ | if(i==p) System.out.println(“i and p are the same object”); | ||
+ | if(i.equals(p)) System.out.println(“ i and p contain the same value”); | ||
+ | |||
+ | In this circumstance, the output is only: | ||
− | + | i and p contain the same value | |
− | + | ||
− | i and p contain the same value. | + | Remember that “==” is always used for object equality, it has not been overloaded for comparing unboxed values. |
This behavior is documented in the [http://java.sun.com/docs/books/jls Java Language Specification] [http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7 section 5.1.7]. Quoting from there: | This behavior is documented in the [http://java.sun.com/docs/books/jls Java Language Specification] [http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7 section 5.1.7]. Quoting from there: | ||
: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''. | :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''. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Incrementing values == | == Incrementing values == |
Revision as of 07:11, 25 June 2007
Equality
Object equality is tested using the == operator, while value equality is tested using the .equals(Object) method. For example:
String one = new String("abc"); String two = new String("abc"); String three = one; if (one != two) System.out.println("The two objects are not the same."); if (one.equals(two)) System.out.println("But they do contain the same value"); if (one == three) System.out.println("These two are the same, because they use the same reference.");
The output is:
The two objects are not the same. But they do contain the same value These two are the same, because they use the same reference.
Integer Caching
Since Java 5 Integer caching was introduced. When creating an Integer using the following code:
Integer myNumber = 10
Or
Integer myNumber = Integer.valueOf(10);
256 Integer objects are created in the range of -128 to 127 which are all stored in an Integer array. This caching functionality can be seen by looking at the inner class, IntegerCache, which is found in Integer:
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); }
So when creating an object using Integer.valueOf or directly assigning a value to an Integer within the range of -128 to 127 the same object will be returned. Therefore, consider the following example:
Integer i = 100; Integer p = 100; if (i == p) System.out.println("i and p are the same."); if (i != p) System.out.println("i and p are different."); if(i.equals(p)) System.out.println("i and p contain the same value.");
The output is:
i and p are the same. i and p contain the same value.
It is important to note that object i and p only equate to true because they are the same object, the comparison is not based on the value, it is based on object equality. If Integer i and p are outside the range of -128 or 127 the cache is not used, therefore new objects are created. When doing a comparison for value always use the “.equals” method. It is also important to note that instantiating an Integer does not create this caching. So consider the following example:
Integer i = new Integer (100); Integer p = new Integer(100); if(i==p) System.out.println(“i and p are the same object”); if(i.equals(p)) System.out.println(“ i and p contain the same value”);
In this circumstance, the output is only:
i and p contain the same value
Remember that “==” is always used for object equality, it has not been overloaded for comparing unboxed values.
This behavior is documented in the Java Language Specification section 5.1.7. Quoting from there:
- 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.
Incrementing values
Be careful of the post-increment operator:
int x = 5; x = x++; System.out.println( x );
Prints 5.