One not very graceful aspect of Java: everything is an Object, except for things that aren’t. (A few basic types: integers of various sizes, floats, booleans, characters, maybe one or two other things that I’m forgetting.) Why is that? The reasons must have something to do with making operations on those basic types more efficient, of course. For example, assuming that you’re on a 32-bit machine, you’d like to be able to store an arrays of 5 integers in only 20 bytes, to be able to add two integers with a single machine operation, etc. So, even if your integer type were to allow method calls (in particular, were to support the methods that Object requires), you wouldn’t want the method calls to be accessed via the normal method call mechanism. Or, perhaps on a more basic level, you would need a mechanism to avoid heap allocation for integer objects.

One way to avoid heap allocation for integer objects but to support it for other kinds of objects is via tagging: if you have a 32-bit value in memory, then the bottom couple of bits tell you if the value is a pointer to an object, an integer, a character, etc. One problem with that is that you lose a couple of bits, so you can only support 30-bit integers via this mechanism. Which is fine for languages like Scheme with arbitrary precision integer arithmetic (so this is just an optimization), but not suitable for Java where integers are defined to have exactly 32 bits of precision. The thing is, though, that’s irrelevant to the Java example, for a couple of reasons, the most basic of which is that I’ve used the word “object” in a completely generic sense in this paragraph, simply meaning “datatype”, which has nothing to do with the existence or lack thereof of an inheritance relationship. The second reason is that Java’s implementation model goes through the Java virtual machine, and while I know next to nothing about it, I’m pretty sure that it has enough strong typing to make type tagging unnecessary. (Otherwise, I don’t see how it could be as secure and efficient as it is claimed to be: either, sure, but not both.)

So that last paragraph was a waste of speculation. And, in fact, Java’s own (as opposed to the JVM’s) strong typing means that you should be able to normally do operations on integers very efficiently, even if integer were thought of as a subclass of Object: when you pass an integer to a function expecting an Object, then at that point the compiler could stick some goop around it to make it behave like an instance of a normal class, but if you’re passing it to a function expecting integers as arguments, then the compiler wouldn’t need to insert that goop. (As is, Java already has classes that correspond to basic types with enough goop added to turn them into honest Objects; in fact, Java 5 does this conversion automatically for you in some circumstances, though by no means all, or even (if I recall correctly) many.)

What flaws would a scheme like that have? It would cause memory allocation to occur behind the scenes in some situations; this might have some surprising consequences at times (in particular, allowing an OutOfMemoryError to be thrown when passing an integer to certain functions), but I don’t think that would be a show-stopper. Equality would be a little delicate: given functions

bool equal( int a, int b ) { return a == b; }

and

bool equalObj( Object a, Object b ) { return a == b; }

you’d certainly want equal(5,5) to hold, and presumably would also want equalObj(5,5) to hold; the latter would make equality testing a little less efficient in some circumstances than it currently is, but I don’t think that’s a bit deal. (Especially since it would only slow down equality testing for variables of type Object: if you know a more specific type, then you’d be safe.)

It would also interact badly with one aspect of Java’s arrays, but that’s a misfeature that I’ll probably whine about in the future.

So I guess I still don’t understand why they didn’t just make everything an Object. Then again, one can ask why I care? If pressed, I would tend to land on the side of languages without a universal superclass. Having said that, I’m not sure I would encourage all languages to provide generic types that are as powerful as C++ templates, and for languages without a mechanism of that power, it will unfortunately be the case that having a class like Object is a necessary evil, in which case you’d want Object to be a universal superclass for all types, not just a superclass for all types except for a few weirdos.

Post Revisions:

There are no revisions for this post.