Old comments about Java

bearophile bearophileHUGS at lycos.com
Sat Apr 23 16:43:26 PDT 2011


I've re-read an old (1997-2000) article about Java. The author seems an expert lisper. Of course some of those comments about Java are obsolete today:
http://www.jwz.org/doc/java.html

I don't remember if I have already shown this article here, I have found only this, from 2001:
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=D&artnum=1319


Some quotations from the article. Some of the following things apply to D too (probably as seen from a CLisp programmer). My few comments are in []:

The fact that static methods aren't really class methods (they're actually global functions: you can't override them in a subclass) is pretty dumb.

This "integers aren't objects" nonsense really pisses me off. Why did they do that? Is the answer as lame as, "we wanted the 'int' type to be 32 bits instead of 31"? (You only really need one bit of type on the pointer if you don't need small conses, after all.)
[In D you are able to define such single-word integers in library code, but they are not the default integer type.]

After all this time, people still think that integer overflow is better than degrading to bignums, or raising an exception?
[Of course not. Maybe D devs will get there.]

I sure miss multi-dispatch. (The CLOS notion of doing method lookup based on the types of all of the arguments, rather than just on the type of the implicit zero'th argument, this).
[Andrei may Ask some CLisp programmers why they like multi-dispatch and what they use it for.]

The finalization system is lame. Worse than merely being lame, they brag about how lame it is! To paraphrase the docs: "Your object will only be finalized once, even if it's resurrected in finalization! Isn't that grand?!" Post-mortem finalization was figured out years ago and works well. Too bad Sun doesn't know that.
[I think this is getting fixed in D2]

Relatedly, there are no "weak pointers." Without weak pointers and a working finalization system, you can't implement a decent caching mechanism for, e.g., a communication framework that maintains proxies to objects on other machines, and likewise keeps track of other machines' references to your objects.
[Weak pointers will eventually be present in Phobos]

The locking model is broken.

    First, they impose a full word of overhead on each and every object, just in case someone somewhere sometime wants to grab a lock on that object. What, you say that you know that nobody outside of your code will ever get a pointer to this object, and that you do your locking elsewhere, and you have a zillion of these objects so you'd like them to take up as little memory as possible? Sorry. You're screwed.
    [I have not yet understood why D shared this Java design choice.]

    Any piece of code can assert a lock on an object and then never un-lock it, causing deadlocks. This is a gaping security hole for denial-of-service attacks.

    In any half-way-rational design, the lock associated with an object would be treated just like any other slot, and only methods statically "belonging" to that class could frob it.


There is no way to signal without throwing: that is, there is no way to signal an exceptional condition, and have some condition handler tell you "go ahead and proceed anyway." By the time the condition handler is run, the excepting scope has already been exited.

The distinction between slots and methods is stupid. Doing foo.x should be defined to be equivalent to foo.x(), with lexical magic for "foo.x = ..." assignment. Compilers should be trivially able to inline zero-argument accessor methods to be inline object+offset loads. That way programmers wouldn't break every single one of their callers when they happen to change the internal implementation of something from something which happened to be a "slot" to something with slightly more complicated behavior.
[This is fixed/done in Scala language]

The notion of methods "belonging" to classes is lame. Anybody anytime should be allowed to defined new, non-conflicting methods on any class (without overriding existing methods.) This causes no abstraction-breakage, since code which cares couldn't, by definition, be calling the new, "externally-defined" methods. This is just another way of saying that the pseudo-Smalltalk object model loses and that generic functions (suitably constrained by the no-external-overrides rule) win.
[This last idea looks like C# extension methods]

Bye,
bearophile


More information about the Digitalmars-d mailing list