Common source of bugs when autoboxing

62 views
Skip to first unread message

Vineet Sinha

unread,
Mar 10, 2012, 3:41:56 PM3/10/12
to java...@googlegroups.com
I just read about this blog post that might be worth pointing out:

The summary: be careful when using '==' with Integers (as opposed to ints).

The problem is sometimes hard to diagnose because Java caches Integer objects from -128 to 127. I remember reading about this when I first started playing with Autoboxing, but this is one of those small details that it is easy to forget.

Regards,
Vineet

Ricky Clarkson

unread,
Mar 10, 2012, 3:46:40 PM3/10/12
to java...@googlegroups.com
Inline image 1

Use a decent IDE and/or static analysis tool, and stop worrying.

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.

equals.png

Jon Kiparsky

unread,
Mar 10, 2012, 3:53:21 PM3/10/12
to java...@googlegroups.com
If an IDE is a way to avoid knowing the language, or to avoid understanding your own code, I'd rather avoid the IDE.
A student who doesn't know that an Integer is an object needs a kicking, not a safety net.
(I say a student, assuming that nobody could possibly be working as a programmer and make this mistake... if I'm wrong, I'm sure I'll read about it on the Daily WTF, no need to make me sad by robbing me of my comforting illusions on a nice Saturday like this one)
equals.png

Fabrizio Giudici

unread,
Mar 10, 2012, 3:57:38 PM3/10/12
to java...@googlegroups.com, Jon Kiparsky
On Sat, 10 Mar 2012 21:53:21 +0100, Jon Kiparsky <jon.ki...@gmail.com>
wrote:

> If an IDE is a way to avoid knowing the language, or to avoid
> understanding
> your own code, I'd rather avoid the IDE.
> A student who doesn't know that an Integer is an object needs a kicking,
> not a safety net.
> (I say a student, assuming that nobody could possibly be working as a
> programmer and make this mistake... if I'm wrong, I'm sure I'll read
> about
> it on the Daily WTF, no need to make me sad by robbing me of my
> comforting
> illusions on a nice Saturday like this one)

You don't know how many pieces of code I've professionally reviewed and
contained that bug. That's why FindBugs is fundamental.

--
Fabrizio Giudici - Java Architect, Project Manager
Tidalwave s.a.s. - "We make Java work. Everywhere."
fabrizio...@tidalwave.it
http://tidalwave.it - http://fabriziogiudici.it

Ricky Clarkson

unread,
Mar 10, 2012, 4:10:27 PM3/10/12
to java...@googlegroups.com
There are plenty of == errors in production Java code.  Remember that not everyone studied Java, or listened, so they will learn on the job, and even if they've already learned before writing the code they don't always get it right.  The last time I saw an == bug was on Wednesday.

Having an IDE actually highlight those things saves me so much time in working out why on earth certain bugs exist.  We can all learn all the corner cases of all the languages, but even when you know them you don't want to have to think about them constantly while reading unfamiliar code.

Also, knowing that Integers are objects isn't the problem, it's that == succeeds sometimes.  Integer x = 100, y = 100; x == y gives true.  replace the 100s with 400 and you get false.  So if you don't know how autoboxing works you might test with 100 and assume that autoboxing affects == (it does, but not when both sides are already reference types) and later see a bug because of a higher value.
equals.png

Jon Kiparsky

unread,
Mar 10, 2012, 4:20:54 PM3/10/12
to java...@googlegroups.com
"Also, knowing that Integers are objects isn't the problem, it's that == succeeds sometimes."

That's for sure. I don't remember who said it, but this is a case of "syntactic sugar leads to cancer of the semicolon". I still say it's the programmers job to know the language, and part of that is knowing that object comparison with == is always wrong, even if the implementers have made a stupid decision to make it work for some arbitrary values. Really, it's not a particularly obscure or subtle fact about the language.

Ricky Clarkson

unread,
Mar 10, 2012, 4:23:28 PM3/10/12
to java...@googlegroups.com
That's lovely, but doesn't help at all when you inherit code that does it wrong. :)

On Sat, Mar 10, 2012 at 6:20 PM, Jon Kiparsky <jon.ki...@gmail.com> wrote:
"Also, knowing that Integers are objects isn't the problem, it's that == succeeds sometimes."

That's for sure. I don't remember who said it, but this is a case of "syntactic sugar leads to cancer of the semicolon". I still say it's the programmers job to know the language, and part of that is knowing that object comparison with == is always wrong, even if the implementers have made a stupid decision to make it work for some arbitrary values. Really, it's not a particularly obscure or subtle fact about the language.

--

Vineet Sinha

unread,
Mar 10, 2012, 7:50:37 PM3/10/12
to java...@googlegroups.com
I am a huge proponent of great tools. But, tools are really only as good as the awareness of such problems (that can easily hide).

If there are any such particular pet problems that are mines waiting to go off, or problems you face on-and-off as a developers or team lead - I would love to hear about them.

Cheers,
-Vineet

Roland Tepp

unread,
Mar 11, 2012, 11:57:32 AM3/11/12
to java...@googlegroups.com
Well... I would say actually, that this is one of these cases where the Language has it wrong ...
... and now every developer dow that road has to pay the tax of knowing that "thee shall never use == for comparing objects for equality. And oh, by the way, Integer is an object too..."

laupäev, 10. märts 2012 23:23.28 UTC+2 kirjutas Ricky Clarkson:
That's lovely, but doesn't help at all when you inherit code that does it wrong. :)

On Sat, Mar 10, 2012 at 6:20 PM, Jon Kiparsky <jon.ki...@gmail.com> wrote:
"Also, knowing that Integers are objects isn't the problem, it's that == succeeds sometimes."

That's for sure. I don't remember who said it, but this is a case of "syntactic sugar leads to cancer of the semicolon". I still say it's the programmers job to know the language, and part of that is knowing that object comparison with == is always wrong, even if the implementers have made a stupid decision to make it work for some arbitrary values. Really, it's not a particularly obscure or subtle fact about the language.

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+unsubscribe@googlegroups.com.

Jon Kiparsky

unread,
Mar 11, 2012, 12:11:04 PM3/11/12
to java...@googlegroups.com
On Sun, Mar 11, 2012 at 11:57 AM, Roland Tepp <luo...@gmail.com> wrote:
Well... I would say actually, that this is one of these cases where the Language has it wrong ...
... and now every developer dow that road has to pay the tax of knowing that "thee shall never use == for comparing objects for equality. And oh, by the way, Integer is an object too..."


I'm not sure how it's difficult to remember how objects work, or to remember that you used a wrapper class precisely because you needed some object-like behavior in your integers. I agree that the language has  got it wrong, but I'd say the problem is more that the minor convenience of autoboxing has apparently got people confused about what Integers are. Another case of syntactic sugar gone wrong.


 
laupäev, 10. märts 2012 23:23.28 UTC+2 kirjutas Ricky Clarkson:
That's lovely, but doesn't help at all when you inherit code that does it wrong. :)

On Sat, Mar 10, 2012 at 6:20 PM, Jon Kiparsky <jon.ki...@gmail.com> wrote:
"Also, knowing that Integers are objects isn't the problem, it's that == succeeds sometimes."

That's for sure. I don't remember who said it, but this is a case of "syntactic sugar leads to cancer of the semicolon". I still say it's the programmers job to know the language, and part of that is knowing that object comparison with == is always wrong, even if the implementers have made a stupid decision to make it work for some arbitrary values. Really, it's not a particularly obscure or subtle fact about the language.

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To view this discussion on the web visit https://groups.google.com/d/msg/javaposse/-/tKKTvZCNqToJ.

To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.

Cédric Beust ♔

unread,
Mar 11, 2012, 12:54:36 PM3/11/12
to java...@googlegroups.com

On Sun, Mar 11, 2012 at 8:57 AM, Roland Tepp <luo...@gmail.com> wrote:
Well... I would say actually, that this is one of these cases where the Language has it wrong ...

I would say that this is an incorrect hindsight. I think that this kind of little detail was very important in 1995 and probably contributed to make Java the success it is today, even if it looks like an odd decision today.

-- 
Cédric

Kevin Wright

unread,
Mar 11, 2012, 1:09:16 PM3/11/12
to java...@googlegroups.com
I'd say smalltalk (a 70's language) had it right, make *everything* an object.

But Java was desperate to attract the many developers already using C++ (an 80's language), and one of the tactics used was to make Java as similar to C++ as possible, including the handling of primitives.  There's also an argument that primitives offer better performance, but there was nothing to stop the Java team using primitives on the JVM whilst still representing them as objects in the language.

If everything is an object, then the solution is simple: make == always use .equals for object types and test directly for equality where primitives are used in the VM.  Reference equality is generally a specialised sort of operation, and better exposed in a way that's far harder to perform accidentally.  Problem solved!


Of course... It would be terribly cynical of me to believe that this whole issue comes down to a marketing requirement, and that we already knew how to do the "right thing" for a good two decades before the language was devised :)


2012/3/11 Cédric Beust ♔ <ced...@beust.com>

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.



--
Kevin Wright
mail: kevin....@scalatechnology.com
gtalk / msn : kev.lee...@gmail.com
vibe / skype: kev.lee.wright
steam: kev_lee_wright

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra

Cédric Beust ♔

unread,
Mar 11, 2012, 1:23:45 PM3/11/12
to java...@googlegroups.com

On Sun, Mar 11, 2012 at 10:09 AM, Kevin Wright <kev.lee...@gmail.com> wrote:
I'd say smalltalk (a 70's language) had it right, make *everything* an object.

Define "right". I used a lot of Smalltalk during my PhD in the early 90's and while the environment was revolutionary on many fronts, it was also very, very slow (both the IDE and the programs it created). I'd argue that one of the many reasons for this was because everything was an object.

Java's decision to optimize this part of the language was instrumental, and even with this, Java was still considered to be a slow language during its early years. I think that if it had chosen Smalltalk's approach, it would have been dismissed like Smalltalk as a language that looks nice on the surface but that cannot be used for production work.

-- 
Cédric

Fabrizio Giudici

unread,
Mar 11, 2012, 3:38:26 PM3/11/12
to java...@googlegroups.com, Cédric Beust ♔
On Sun, 11 Mar 2012 18:23:45 +0100, Cédric Beust ♔ <ced...@beust.com>
wrote:

> On Sun, Mar 11, 2012 at 10:09 AM, Kevin Wright
> <kev.lee...@gmail.com>wrote:
>
>> I'd say smalltalk (a 70's language) had it right, make *everything* an
>> object.
>
>
> Define "right". I used a lot of Smalltalk during my PhD in the early 90's
> and while the environment was revolutionary on many fronts, it was also
> very, very slow (both the IDE and the programs it created). I'd argue
> that
> one of the many reasons for this was because everything was an object.

In fact SmallTalk, from the industrial point of view, is a failure.
Fortunately Java has got non-object primitives and it allows to do number
crunching. All this discussion originates from a typical programmer's
error blaming the language, and for controlling that error we've got
plenty of tools, as if it was the only error that programmers do in Java.

Kevin Wright

unread,
Mar 12, 2012, 12:47:34 PM3/12/12
to java...@googlegroups.com, Cédric Beust ♔
Primitives are good... if you're a CPU.  I have absolutely no objection to the performance benefits of primitives in bytecode (in the earlier pre-JIT interpreters at least, the benefit is less clear in a post-JIT world).

But what's in bytecode for the benefit of the compiler needn't be what's in the language for the benefit of programmers.  A translation in javac would allow Java to have pure objects whilst maintaining primitives in bytecode; just as javac allows us to create inner classes, even though the underlying platform has no idea of the concept.  We *can* have our cake and eat it too.

As for why it's right for everything to be objects?  It's a far cleaner, more elegant, and a more internally consistent model for programmers to reason about.  The very existence of this thread illustrates why that's important!

To quote: "premature optimisation is the root of all evil", and you can't get much more premature than in the design of a language...

Fabrizio Giudici

unread,
Mar 12, 2012, 12:53:49 PM3/12/12
to java...@googlegroups.com, Kevin Wright, Cédric Beust ♔
On Mon, 12 Mar 2012 17:47:34 +0100, Kevin Wright
<kev.lee...@gmail.com> wrote:

> Primitives are good... if you're a CPU. I have absolutely no objection
> to
> the performance benefits of primitives in bytecode (in the earlier
> pre-JIT
> interpreters at least, the benefit is less clear in a post-JIT world).
>
> But what's in bytecode for the benefit of the compiler needn't be what's
> in
> the language for the benefit of programmers. A translation in javac
> would
> allow Java to have pure objects whilst maintaining primitives in
> bytecode;
> just as javac allows us to create inner classes, even though the
> underlying
> platform has no idea of the concept. We *can* have our cake and eat it
> too.
>
> As for why it's right for everything to be objects? It's a far cleaner,
> more elegant, and a more internally consistent model for programmers to
> reason about. The very existence of this thread illustrates why that's
> important!
>
> To quote: "premature optimisation is the root of all evil", and you can't
> get much more premature than in the design of a language...

I won't object to anything you wrote - I'm just pointing out that in 1995
betting that the compiler could do all the involved magic, and in an
efficient way, was probably a hazardous bet.

Josh Berry

unread,
Mar 12, 2012, 1:30:37 PM3/12/12
to java...@googlegroups.com
On Mon, Mar 12, 2012 at 12:53 PM, Fabrizio Giudici
<Fabrizio...@tidalwave.it> wrote:
> I won't object to anything you wrote - I'm just pointing out that in 1995
> betting that the compiler could do all the involved magic, and in an
> efficient way, was probably a hazardous bet.

I also think it is probably an overstatement to think it was the
existence of primitives that "won" the battle for java, and not a
ridiculously effective marketing push by those involved.

Cédric Beust ♔

unread,
Mar 12, 2012, 2:08:10 PM3/12/12
to java...@googlegroups.com
No single criterion won, obviously, but I think that Java's decision to use primitives was instrumental to its success. Java almost died many times during its early years for performance reasons but somehow, it survived and eventually, compiler and VM technology put it over that bump. Who knows, maybe it would never have made it out of there if it had gone the "everything is an object" way.

Also, I really don't buy for a second that marketing was important to Java's success. The developer community and the growing infatuation for live web pages at the time is what made Java cross the gap, not Sun's (fairly feeble, for people who remember these days) marketing.

-- 
Cédric

Josh Berry

unread,
Mar 12, 2012, 2:53:42 PM3/12/12
to java...@googlegroups.com
On Mon, Mar 12, 2012 at 2:08 PM, Cédric Beust ♔ <ced...@beust.com> wrote:
> Also, I really don't buy for a second that marketing was important to Java's
> success. The developer community and the growing infatuation for live web
> pages at the time is what made Java cross the gap, not Sun's (fairly feeble,
> for people who remember these days) marketing.

I don't recall it being that feeble. Seemed that Sun took great
efforts to get Java in many college intro courses.

Joseph Darcy

unread,
Mar 12, 2012, 3:42:13 PM3/12/12
to java...@googlegroups.com

See Doug Lea's

"Some Questions and Answers about using Java in Computer Science Curricula,"
http://g.oswego.edu/dl/html/javaInCS.html

written circa 1996.

-Joe

Kevin Wright

unread,
Mar 12, 2012, 3:51:02 PM3/12/12
to java...@googlegroups.com

Marketing helped (especially to schools/universities), as did garbage collection and low level concurrency primitives out of the box, faster compilation, saner error messages, and a rich standard library available for free (including AWT).

But I don't believe that anybody every thought "ooh, primitives, I must use this language because it'll be so fast".  Not when it was (then) interpreted, and therefore slow for other reasons.  The only real benefit of primitives was an apparent passing familiarity to C++ devs.

--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.

Ricky Clarkson

unread,
Mar 12, 2012, 7:28:26 PM3/12/12
to java...@googlegroups.com
Incidentally, the presence of primitives is not the problematic part of the bug that started this thread, but the useless behaviour of ==.

C# has primitives, but List<int> works, 5.ToString() works and if you do happen to use Int32 instead of int, its == actually does the right thing (compares the int, not the pointer).  You can still get at the Java-like behaviour by casting both sides to object.

In case anyone thinks that this is because .NET has reified generics:

Scala doesn't really have primitives, but doesn't allocate a wrapper object for Ints unless it really needs to, and in Scala List[Int] works, 5.toString works and if you do happen to use java.lang.Integer instead of Int, its == actually does the right thing (compares the Int, not the pointer).  I'm not sure how you get at the Java-like behaviour though, never needed it.

Cédric Beust ♔

unread,
Mar 12, 2012, 7:43:11 PM3/12/12
to java...@googlegroups.com
On Mon, Mar 12, 2012 at 4:28 PM, Ricky Clarkson <ricky.c...@gmail.com> wrote:
Scala doesn't really have primitives, but doesn't allocate a wrapper object for Ints unless it really needs to, and in Scala List[Int] works, 5.toString works and if you do happen to use java.lang.Integer instead of Int, its == actually does the right thing

Yup but in doing so, Scala managed to break a few other things along the way:

scala> 1==1.0
res1: Boolean = true

scala> 1.equals(1.0)
res2: Boolean = false

-- 
Cédric





Ricky Clarkson

unread,
Mar 12, 2012, 7:48:19 PM3/12/12
to java...@googlegroups.com
Equality is always a tricky one!

I guess they could solve that by disallowing explicit .equals calls.  As Int <: Any rather than AnyRef (AnyRef is analogous to Object whereas Any is the supertype of both direct and reference types) there's no obligation to provide .equals that I can see.

2012/3/12 Cédric Beust ♔ <ced...@beust.com>

Kirk Pepperdine

unread,
Mar 13, 2012, 3:12:12 AM3/13/12
to java...@googlegroups.com
On 2012-03-12, at 7:08 PM, Cédric Beust ♔ wrote:


On Mon, Mar 12, 2012 at 10:30 AM, Josh Berry <tae...@gmail.com> wrote:
On Mon, Mar 12, 2012 at 12:53 PM, Fabrizio Giudici
<Fabrizio...@tidalwave.it> wrote:
> I won't object to anything you wrote - I'm just pointing out that in 1995
> betting that the compiler could do all the involved magic, and in an
> efficient way, was probably a hazardous bet.

I also think it is probably an overstatement to think it was the
existence of primitives that "won" the battle for java, and not a
ridiculously effective marketing push by those involved.

No single criterion won, obviously, but I think that Java's decision to use primitives was instrumental to its success.

+1 but not for performance reasons. Smalltalk implemented primitives as primitives but didn't directly expose that implementation in the language as Java did. Consequently Smalltalk performance was better than Java but the advantage was Java looked similar to what people were used to where as Smalltalk was just "weird".

Kirk

Roland Tepp

unread,
Mar 13, 2012, 3:55:50 AM3/13/12
to java...@googlegroups.com
My point exactly.

It's not the existence of primitives, but the broken behavior of == operator.

Even back in those days, I remember, how some languages had === operator for comparing instances (i.e. pointers to an object), allowing == operator to behave in a most intuitive manner, while still giving rather simple method for testing object identity.
Reply all
Reply to author
Forward
0 new messages