Lambda the Ultimate

inactiveTopic Joshua Bloch interview on new features in Java 1.5
started 5/10/2003; 11:49:56 PM - last post 5/15/2003; 12:23:39 AM
Ehud Lamm - Joshua Bloch interview on new features in Java 1.5  blueArrow
5/10/2003; 11:49:56 PM (reads: 2251, responses: 17)
Joshua Bloch interview on new features in Java 1.5
(from the LtU discussion group)

Kimberley was kind enough to alert us to this interview regarding the new language features in Tiger (J2SE 1.5).

Nothing earth shattering: generics, enhanced for loops, autoboxing/unboxing, enums, static import and metadata.

We discussed most of these features before, but the interview is nice in that it give small code examples.

From a more abstract point of view it is nice to comapre the evolution of C++ we discussed at length this week, with the evolution of Java.

It is also interesting to notice the time it takes for new features to enter a programming language. We are not talking about ideas that come from Academia, mind you. Generics were implemented in Ada in 1983, and are used heaviliy. C++, as we all know, has them for years. Even the proposals for Java generics are now several years old.

But we'll get there. You can't stop progress.


Posted to general by Ehud Lamm on 5/11/03; 12:13:01 AM

Ehud Lamm - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/11/2003; 7:46:05 AM (reads: 1175, responses: 0)
I see enums will be extendible via inheritance. Is this really a good thing? Opinions, anyone?

Dan Shappir - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/11/2003; 8:48:21 AM (reads: 1170, responses: 2)
I think its a good idea for a very simple reason: it's a feature I wish I had when programming in C++. It generally happens when I build on top of existing functionality, without wanting to change it, e.g.:

enum VALUES { ... }
void foo(VALUES v);

is extended by:

enum VALUES2 : public VALUES { ... }
void foo2(VALUES2 v);

foo works the same way as before, accepting only values it can handle, while foo2 can handle the original values and new values.

The obvious problem is the "fragile base class" issue. That is, what happens if VALUE is extended to include new values. If we are lucky the new values added to VALUES will conflict with existing values in VALUES2 and we get a compile error. If we are unlucky foo2 may receive argument values it doesn't know how to handle.

Still, the fragile base class is an issue with all types of implementation inheritance and not specific to this case.

Dan Shappir - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/11/2003; 9:25:05 AM (reads: 1178, responses: 1)
Put in more general terms: it makes as much sense to extend an enum as it does any other user-defined type. Since implementation inheritance if a cornerstone of OOP (at least in the Java style) its only fitting.

andrew cooke - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/11/2003; 10:19:20 AM (reads: 1133, responses: 0)
There's a comment in the interview about avoiding adding new keywords. The same thing crops up in Python discussion. Why can't people defining a new language choose a syntax that avoids this problem (ie that can be parsed without needing to know that certain words are keywords to resolve what would otherwise be ambiguous statements)? I've only implemented two parsers (via separate tools - I guess there's been quite a bit of ad-hoc recursive top down "parsing" at various points) in my life and even I've already learnt that keywords are nasty, so surely experts should know better. I guess it's a C legacy thing (and maybe a Lisp legacy thing too, in a negative way). Oz/Mozart manages to get quite close to C (closer than ML or Haskell, for example) while avoiding (I believe) this problem, so I'm not sure why Java should be broken in this way.

Or have I misunderstood? :o)

andrew cooke - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/11/2003; 10:29:03 AM (reads: 1134, responses: 5)
Implicit conversion of null to zero on unboxing?!

Dan Shappir - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/11/2003; 11:24:23 AM (reads: 1171, responses: 0)
There is an additional important point with regard to enum inheritance that I thought of on the way home form work. The automatic type conversions that are defined by the inheritance relationship should work in reverse for enums than the way they do for regular classes.

Consider a class D derived from a class B. Java allows a reference to an object of type D to be used wherever a reference to an object of type B is expected. Using a reference to B where a reference to D is expected requires an explicit cast, and can result in a run-time exception if the object is not the correct type.

Given my previous example, Java should allow an automatic conversion from a value of type VALUES to a value of type VALUES2, because VALUES is a subset of VALUES2. The reverse conversion should require a cast, and result in a run-time exception if the value does not belong to the VALUES set. I don't know if Java 1.5 implements this feature in this way.

This is sort of related to Tim Sweeney's posts on type theory.

Ehud Lamm - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/11/2003; 2:14:31 PM (reads: 1118, responses: 4)
I also found that strange.

andrew cooke - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/11/2003; 2:35:54 PM (reads: 1126, responses: 3)
Maybe Sun engineers have only got to addition in their maths class?

More seriously, it's not as bad as I first thought. I think the reflex horror is largely based on using null as the empty list, but it doesn't work that way in Java - an empty iterator is empty (it doesn't return null) (as I'm sure you know). But even so. I guess they don't have any DB people on their team (I've just been reading one of Celko's books on SQL - not as good as I'd expected, does anyone know of anything better? (don't ask "better in what way?" - you know if a book is good)). While I don't think it will do much harm (apart from looping over result sets from SQL), I can't think of any example where it would be useful. Is there some part of Swing, say (I don't do Java GUI much), that is helped by assuming null implies zero?

Kimberley Burchett - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/11/2003; 3:30:45 PM (reads: 1076, responses: 0)
The fact that enums can be extended via inheritance is a direct consequence of the implementation strategy they chose. They use the "typesafe enum pattern", which means that each enum value is represented by an instance of a given class. Since classes can be extended, therefore so can enums. And since enums are just classes, downcasts are implicit while upcasts are not.

They basically just codified the current idea of best practices. I bet that if they gave any thought at all to the idea of allowing implicit upcasting (instead of implicit downcasting), that they dismissed it as being too weird.

Besides, changing the behavior of implicit casts would have required a change to the vm's bytecode verifier. Java 1.4 already broke bytecode compatibility, and nobody would have tolerated it happening again in 1.5. Also, requiring changes to the verifier suggests that implicit upcasting might open up security holes in some situations.

I suspect that most companies will simply decide that extending an enum is bad, and just ban it in their style guides.

Frank Atanassow - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/12/2003; 5:50:04 AM (reads: 1014, responses: 0)
The automatic type conversions that are defined by the inheritance relationship should work in reverse for enums than the way they do for regular classes.

XML Schema has a notion of subtyping like this. Basically, if you have a type X (which is a regular expression) which involves a choice, then you can declare any type Y which fixes that choice to be a subtype. For example, if X is:

author*, title, year

and Y is:

author, title, year

then Y can be declared to be a `restriction' of Y, since author* is type-equal to (1|author+), so it fixes a choice. (`1' is the empty sequence.)

I found this rather interesting; you might call it `additive' subtyping in contrast to the usual notion of subtyping where you extend a record, which might be called `multiplicative' subtyping. You can model these subtyping relations via coercions: additive refinements are modeled by injections of sums and multiplicative ones by projections of products.

Daniel Bonniot - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/12/2003; 6:35:17 AM (reads: 1068, responses: 0)
They give an example in the article where treating null as zero is what you want. But I agree this seems very ad-hoc. It just happens that in that case they are counting occurences, stored in a Map, in which case absebt naturally means 0. It's just as easy to imagine cases where the "default value" should be 1 (a multiplicative coefficient), some other integer, or rather reveal a bug, like that a wrong key was entered in the map.

From the point of view of the Nice language, all this confusion seems to result from Java's (and other language's) inability to express possibly-null and non-null types. For instance, when you have a Map<String, int> map, then map.get(key) has type ?int. That is, the value is either an int, or null if there is no mapping for that key. Therefore, you need to test this result against null before treating it as an int. Consequently, the type system guarantess that you never get NullPointerException.

Nice also has the x || y operator: if x has type ?T and y has type T, then x || y has type T. It evaluates to the value of x, unless it is null, in which case it has the value of y. So in their example you could simply write map.get(key) || 0, which has type int.

Matt Hellige - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/12/2003; 7:48:49 AM (reads: 1056, responses: 1)
More seriously, it's not as bad as I first thought.

I think it's absolutely as bad as I first thought! Using Integer objects with null is a pretty common idiom in Java to implement functionality like ML's 'a option type or Haskell's Maybe a type. Having null automatically converted to 0 makes this awkward at best, maybe impossible. Imagine the reaction if Simon Peyton Jones announced that in the next version of Haskell, Maybe Int and Int would be equivalent, and NONE would be considered equal to 0...

To launch something of a tangent, the real problem exposed here is that using null in this way is evil, and a much nicer (and still very OO) solution would be to define a MaybeInt class for this purpose (or, with generics, the much more useful Maybe<*>). Unfortunately, class definition is too heavyweight for this, inner classes are ugly, and performance-conscious people tend to be enormously wary of creating "spurious" wrapper objects. This, in my opinion, is the much more serious problem with Java, and the one also manifested in the int/Integer distinction. It's quite awful to have an object-oriented language that discourages you from using objects... Imagine a functional language in which you were told, in all seriousness, to try to avoid defining too many functions!

Daniel Bonniot - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/12/2003; 2:10:24 PM (reads: 1030, responses: 0)
In Nice, ?T corresponds to what you call Maybe<T>. It entirely resides in the type system, so no wrapper class is used in the generated code, which should reinsure performance-conscious people.

(In the current implementation, wrappers are used, but only for primitive values.)

andrew cooke - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/13/2003; 4:45:56 PM (reads: 902, responses: 1)
A practical point - if you don't want enums to be subclassed then they (ie the class you use to subclass theirs) can be declared final.

Dan Shappir - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/13/2003; 11:36:49 PM (reads: 903, responses: 0)
But the point is that I do want inheritance for enums, just not the way they seem to be going about it. So basically what you're saying is that I'll get the feature but I should be careful never to use it. Is that a Good Thing?

Ehud Lamm - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/14/2003; 10:17:35 PM (reads: 822, responses: 1)
I received the following encouraging email from Joshua Bloch.

Hi. I glanced at your blog article regarding my recent interview on java.sun.com. I just wanted to correct one misconception and provide one update:

The enum feature, as currently construed, will *not* allow inheritance, for precisely the reason that people discussed: the "inverted inheritance relationship" is too confusing to programmers. There are a number of other technical complications too. In the final analyisis, we felt the costs far outweighed the benefits.

Regarding auto-unboxing of null to zero, people overwhelmingly told us not to do this, so we almost certainly won't.

Dan Shappir - Re: Joshua Bloch interview on new features in Java 1.5  blueArrow
5/15/2003; 12:23:39 AM (reads: 840, responses: 0)
It's nice to know they listen :-)

OTOH,

the "inverted inheritance relationship" is too confusing to programmers.

Is that the reason, or, as Kimberley pointed out:

changing the behavior of implicit casts would have required a change to the vm's bytecode verifier. Java 1.4 already broke bytecode compatibility, and nobody would have tolerated it happening again in 1.5

Probably both I guess ...