10 Replies Latest reply: Dec 14, 2009 9:30 PM by jtahlborn RSS

    Problem with "==", "wrap/unwrap" or "Integer"?

    843798
      Not sure if this is the right group to post, but here is the question.
      Why the "Integer" less than 128 can use "==", but not equal to or greater than 128? See following example.

      public class TestEqual {
           public static void main (String[] args) {
                Integer i1, i2, i3, i4;
                i1=127;
                i2=127;
                i3=128;
                i4=128;
                System.out.println(i1 == i2);
                System.out.println(i3 == i4);
           }
      }

      Result is:
      true
      false
        • 1. Re: Problem with "==", "wrap/unwrap" or "Integer"?
          843798
          Because autoboxing uses Integer.valueOf(int)
          • 2. Re: Problem with "==", "wrap/unwrap" or "Integer"?
            843798
            Is the autoboxing behaving different for values 127 and 128? Sorry, still don't understand.
            • 3. Re: Problem with "==", "wrap/unwrap" or "Integer"?
              796085
              lipingyuan wrote:
              Is the autoboxing behaving different for values 127 and 128? Sorry, still don't understand.
              Yes.

              Which is why autoboxing is evil.

              Integer.valueOf() for numbers in the range -128 to +127 (or maybe 0 to +127, I can't remember) return the same Integer object (i.e. they're precomputed/cached). Whereas, Integer.valueOf() for numbers outside this range return a new Integer object for every call.
              • 4. Re: Problem with "==", "wrap/unwrap" or "Integer"?
                843798
                Thanks for your explaination. Is this documented in API or somewhere? I just looked the API but couldn't find it.
                • 5. Re: Problem with "==", "wrap/unwrap" or "Integer"?
                  843798
                  lipingyuan wrote:
                  Thanks for your explaination. Is this documented in API or somewhere? I just looked the API but couldn't find it.
                  [Integer.valueOf(int i)|http://java.sun.com/javase/6/docs/api/java/lang/Integer.html#valueOf%28int%29]

                  "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."

                  ~
                  • 6. Re: Problem with "==", "wrap/unwrap" or "Integer"?
                    3004
                    dannyyates wrote:
                    lipingyuan wrote:
                    Is the autoboxing behaving different for values 127 and 128? Sorry, still don't understand.
                    Yes.

                    Which is why autoboxing is evil.
                    Autoboxing is fine. At least it's no more evil in this sense than the String constant pool is. As long as one understands that you should always use equals() to compare contents, the fact that == sometimes produces what appears to be a false positive can either be regarded as a curious bit of magic that's not understood and therefore not to be relied upon, or it can be investigated as it is being here.
                    • 7. Re: Problem with "==", "wrap/unwrap" or "Integer"?
                      796085
                      jverd wrote:
                      dannyyates wrote:
                      lipingyuan wrote:
                      Is the autoboxing behaving different for values 127 and 128? Sorry, still don't understand.
                      Yes.

                      Which is why autoboxing is evil.
                      Autoboxing is fine. At least it's no more evil in this sense than the String constant pool is. [...]
                      Except that one can easily imagine a method which looks like this:
                      public void method(int a, int b) {
                          // ...
                          blah blah a==b blah
                          // ...
                      }
                      that then gets changed to:
                      public void method(Integer a, Integer b) {
                          // some special null handling as a new use-case for this method
                          // ...
                          blah blah a==b blah
                          // ...
                      }
                      Now, suddenly, this method changes its behaviour in the following ways:
                      1) Things which never used to be == now magically are (your test cases did cover values > 128, didn't they?)
                      2) You're generating garbage that you might not notice (important in low-latency systems)

                      I'm all for auto-unboxing, but auto-boxing is just plain evil because it breaks in mysterious ways.
                      • 8. Re: Problem with "==", "wrap/unwrap" or "Integer"?
                        843798
                        dannyyates wrote:
                        jverd wrote:
                        Autoboxing is fine. At least it's no more evil in this sense than the String constant pool is. [...]
                        Except that one can easily imagine a method which looks like this:
                        public void method(int a, int b) {
                        // ...
                        blah blah a==b blah
                        // ...
                        }
                        that then gets changed to:
                        public void method(Integer a, Integer b) {
                        // some special null handling as a new use-case for this method
                        // ...
                        blah blah a==b blah
                        // ...
                        }
                        Now, suddenly, this method changes its behaviour in the following ways:
                        1) Things which never used to be == now magically are (your test cases did cover values > 128, didn't they?)
                        Other way around;
                        Things which used to be == now no longer are
                        • 9. Re: Problem with "==", "wrap/unwrap" or "Integer"?
                          796085
                          tschodt wrote:
                          Things which used to be == now no longer are
                          Err... yes... that. :-)
                          • 10. Re: Problem with "==", "wrap/unwrap" or "Integer"?
                            jtahlborn
                            dannyyates wrote:
                            jverd wrote:
                            dannyyates wrote:
                            lipingyuan wrote:
                            Is the autoboxing behaving different for values 127 and 128? Sorry, still don't understand.
                            Yes.

                            Which is why autoboxing is evil.
                            Autoboxing is fine. At least it's no more evil in this sense than the String constant pool is. [...]
                            Except that one can easily imagine a method which looks like this:
                            public void method(int a, int b) {
                            // ...
                            blah blah a==b blah
                            // ...
                            }
                            that then gets changed to:
                            public void method(Integer a, Integer b) {
                            // some special null handling as a new use-case for this method
                            // ...
                            blah blah a==b blah
                            // ...
                            }
                            Now, suddenly, this method changes its behaviour in the following ways:
                            1) Things which never used to be == now magically are (your test cases did cover values > 128, didn't they?)
                            2) You're generating garbage that you might not notice (important in low-latency systems)

                            I'm all for auto-unboxing, but auto-boxing is just plain evil because it breaks in mysterious ways.
                            or, it gets changed to:
                             public void method(Object a, Object b) {
                                 // some special null handling as a new use-case for this method
                                 // ...
                                 blah blah a==b blah
                                 // ...
                             }
                             
                            and more hilarity ensues. unfortunately, autoboxing can't be blamed for this one. i think autoboxing is nice because it removes a lot of unnecessary code. the only time i am concerned by it is when it makes potential NPE's less obvious (because the object dereferencing is less obvious). but a good ide should point that out for you, right...?