Has boxing ruined java?
807603Feb 25 2008 — edited Feb 28 2008Sorry, to sound melodramatic, but I think it has, and I think the same problem has manifested itself with strings too. I'm not knocking java by any means, but with all the new additions to the language and ensuring backwards compatibility it's almost imossible without an indepth knowledge of the internals of the methods and knowing how java works to understand whether a simple operation such as comparing two numbers will actually work.
You have to know (presume I'm talking about number objects where necessary, e.g. Integer, Long, etc):
a) whether the number is greater or smaller than 128
b) whether the number was created using 'new' or created implicitly by assigning a value at declaration time
c) how .equals works internally (e.g. you can't compare a long primitive of one value to an Integer object holding the same value)
d) how certain combinations of the above and others do different things.
I wrote a little program in java that compared two numbers (having the same value) together, using combinations of:
- primitives and number objects
- using == and .equals()
- using new number objects on the heap, number objects created without new
- big numbers and small numbers (<128 and > 127)
- different types (e.g. Integer and Long).
Each test gave completely different answers. Of course, you probably say well that's right, that's how it works. But it shouldn't be, Java should be there to shield you from the internals of the system and more importantly, it should be both intuitive and obvious.
btw, the answers from java were:
int a == b (5)
int a == b (500)
new integer a != b (5)
new integer a .equals b (5)
new integer a != b (500)
new integer a .equals b (5)
integer a == b (5)
new integer a .equals b (5)
integer a != b (500)
new integer a .equals b (5)
you can't reference compare Long to an Integer object
new integer/long a ! .equals b (5)
integer/long a != b (500)
new integer/long a ! .equals b (5)
In other words, it varies depending on how you instantiate the variable, the value of the variable (e.g. less than 128) and whether you create it implicitly on the heap or let java create it for you. In some cases it fails to compile.
I repeated the same code in c# (I'm no Microsoft or c# fanboy - it was the nearest similar language to choose from) using the same code (well, instead of int and long I did int and double as long object is just a bigger int object in the c# world) and the result was true for every instance of my comparison.
Don't you think this is how java should have implemented boxing/unboxing, i.e. remove the need to know how the internals of everything works and simply do as you expect, regardless of the value and the type? The fact that number objects are treated differently (i.e. you can create without instantiation, you can compare primitives against them, etc) should mean they are handled as if they were numbers.
I really do think java 1.4 onwards was/is designed by committee, and that is sad.
This is what I think should be done differently:
1. overload == to make number objects test for equality
2. ensure it doesn't matter if your number is greater or smaller than 127
3. add a CompareTo or equivalent for those that (and I've never met anyone that needed to, ever) need to compare number references.
4. make backwards compatibility just that, for those needing old code to work, use -source flag as they do with assert statement. This would also ensure var..args are checked more sensibly in the order of things
5. while I'm here, make string comparisons more sensible as well, rather than having to know how the string was created, by overloading == too.
Thanks for listening, and apologies for the rant, it's just this really really annoys me and I think it spoils Java. I think they did this just to make the SCJP harder ;)
Neil.