Skip to main content

Feel of Java Revisited

Posted by cayhorstmann on March 1, 2008 at 6:20 PM PST

style="margin-right: 2em; float: left;" /> On February 28, James Gosling gave
a presentation in Sun's Santa Clara Campus auditorium (formerly a part of the
Insane Asylum
:-)), entitled “Feel of Java Revisited”. The
talk promised to revisit the classic href="">Feel of Java
paper that famously declared “Java is a blue collar language”.
(SJSU students: Go href="">here
for free access to the paper.)

I teach a graduate class in programming languages at San Jose State University. Instead of covering
denotational semantics or logic programming, I decided to cover what is hot
in dzone (closures, metaobject protocols,
etc.) and smuggle in the theory under the radar. My class has been learning
about the various closure proposals for Java, and we played with the href="">BGGA and href="">CICE implementations in the labs. (If you
want to play along, go href="">here
for a guest login. Sorry, no href="">FCM
yet. The implementation came after I designed the lab.)

style="margin-left: 2em; float: right;" />

Aaron Houston, the tireless champion of the href="">Java Champions, got my class
tickets for the event, with reserved seating, free T-shirts and a
Sun Spot kit for the CS club. Thanks Aaron!!! We all had an amazing time.

src="" />

Much to my disappointment, the presentation did not engage in mudslinging
about competing closures proposals :-) Instead, James revisited his personal
journey to Java. It was very interesting to see how his experience with prior
scripting languages and compiler projects shaped his thinking. When Java was
created, the “blue collar” language was C. Used by Real
Programmers who were manly enough to spend weeks tracking down obscure memory
corruption errors. Garbage collectors were used by href="">quiche eaters.
James explained his goal of combining a familiar syntax with the features
that are required for security and reliability. He also recounted his many
years of experience with virtual machines, from industrial and academic
projects. It became apparent how Java—the happy marriage of blue collar
and quiche eater programming—was no accident but the result of a
careful design process.

Of course, closures came up in the Q&A. James said that he personally
loves closures and would like to use them in Java if and when they become a
part of it. (There had been some speculation in the blogoshpere whether
closures fail the “blue collar test”, which James refuted in href="">this blog.) I asked about
the decision process that governs the evolution of the Java language. In
response, James grumbled a bit about issues with the JCP process. James made
it clear that he considers generics a great win, despite some of the ugly
corner cases. Kirk Pepperdine asked about Java FX and whether it was
competitive with Flex and Silverlight. James gamely said that it will be an
interesting battle. There was some discussion about the successor of Java,
and James said that the JVM is more important than Java itself.

This all left me thinking about closures and blue collar programmers. 15
years ago, only the super-rich had a href="">plasma TV,
and only eggheads used a garbage collector. Now, flat screen TVs are
everywhere, and I can't think of a recent programming language that doesn't
have garbage collection. Time marches on, and what was once a luxury becomes
commonplace in blue collar households.

Consider this example from my homework assignment. Instead of href="">this mess of code,
use BGGA closures to put work on a background thread or the event dispatch
thread like this.

            Scanner in = new Scanner(new FileInputStream(file));
               int lineNumber = 0;
               while (in.hasNextLine())
                  String line = in.nextLine();
                     statusLine.setText("" + lineNumber);

Note how much clearer the code has become. Put time-consuming work on the
background thread, and put the UI update on the EDT. Java FX needs special
keywords for this. With closures, you just define a couple of utility
functions. It is so easy that one of my students wrote:

Last time, it took me at least 10 hours to do one of the problem, but i
got through #1 in less than 1/2 an hour. most of it was copy and paste. I
didn't even need more than 1 class. am i missing something? It's almost as
if you can lift the solution out of the labs. All I had to do was write 2
really really really simple closures.

It doesn't get more blue collar than that :-)

Related Topics >>


Last try. Great thing to make mistakes when questioning readability ;) public U(T) converter(T a(), U b(), U c(T)) { return U (T t) { return a().equals(t) ? b() : c(t); }; }

Hum, there is missing a t inside last line c() (where is my correction function ;)). Should be: public U(T) converter(T a(), U b(), U c(T)) { return U (T t) {a().equals(t) ? b() : c(t) }; }

To me, it is questionable, if control abstractions (or control invocation syntax) should be allowed for restricted-closure cases. It makes a statement look as if it is executed in the given control flow, while it may be taken from it and executed concurrently. As tobega stated, you might be accessing visually owned locks or streams, that do not exist anymore when the statement is executed.

Just to compare a bit on readability (where I think that the declaration of T and U is missing the BGGA example because of HTML-erasure), what about this one: public <T, U> U(T) converter(T a(), U b(), U c(T)) { return U (T t) {a().equals(t) ? b() : c() }; } Anyone having a problem semantically understanding that syntax?

Heh. A contrived example (that of SwingWorker) to push BGGA. I wonder how the same audience would react to this "simple" beauty from the BGGA stable (from Stephen Colebourne's blog ) : public {T => U} converter({=> T} a, {=> U} b, {T => U} c) { return {T t => a.invoke().equals(t) ? b.invoke() : c.invoke(t)}; }

Can you please show us the full code for closure version of "the mess"?

Actually, you would have gotten your line counting right if you hadn't tried to circumvent the "final" restriction by the "array trick", final int[] lineNumber = new int[1];. A final int currentLineNumber = ++lineNumber; before you dispatch the update to the EventQueue would be just what's required. (OK, I am making an assumption that you actually intended the statusLine to show the number of lines added to the textArea, I may be wrong)

Cay.... Really a pleasure to have your class come to this event...and hopefully we'll see what your students can do with those Sun Spots... for a listing of very informative YouTube videos about the Spots go to Terrence Barr's blog entry here:

"Spots Videos"

and Stefano Sanna did an interesting Spots demo at Sun Tech Days Milan that is here: "Spots Preso Milan"

Stay in touch! let us know how you're doing!

Aaron Houston -- Program Coordinator

Java Champions Java User Groups Technology Outreach Sun Microsystems, Inc Menlo Park, Ca

Cay: Interesting post. Glad to see someone getting some use out of the CICE prototype :-)

bharathch: that example from Stephen's blog is a bit contrived anyway - it's far from simple under any of the proposals, or even in Java 6. The comments on his next entry show the equivalent using normal interfaces. I'll reproduce it here since it's short:

public <T, U> Transformer<? super T, ? extends U> converter(Factory<? extends T> a, Factory<? extends U> b, Transformer<? super T, ? extends U> c) { return {T t => a.invoke().equals(t) ? b.invoke() : c.invoke(t)}; }
There are a number of observations we can make about both versions, but those wildcards certainly don't make it any simpler to me.

Please, either post the original mess and the BGGA version each in their entirety, or only show the "meat" of each. I don't see how one is simpler than the other at all. Both are, in their entirety, is a bit of a mess. Bot are, when you just show the essentials, simple.

There's also a bit of a strawman argument here. If that original looks messy to you, then clean it up. I certainly wouldn't leave it like it is. An anonymouse inner class with an embeded Thread class with a one-element-array kludge to get around "the final problem" and so on.

If someone's really writing code like this, they need to first learn how to write clean code in general. Closures might make this specific code cleaner, but the real solution is for the person to try harder (or have a mentor to explain how) to clean up this code.

Since you forget to dispose properly of your InputStream, let me help you with another little closure-based utility: with(in) { onBackgroundThread() { .... } } Oops, the stream got closed before the background thread ran.

In both your closure-based and non-closure code the status line will probably show a line number that is higher than the actual line added to the text area.

Getting threading right does not get easier by introducing constructs that simplify the process of getting threading wrong. See my blog:

If you use named private inner classes instead, your code is broken down into smaller units to parse, I believe that would still be considered better practice than having large clumsy methods. With a proper constructor on the inner class you can more easily see how to capture the momentary state you need.

I thought Neal himself said (in one of the video talks floating around) that he wouldn't expect the Control Abstraction syntax to be used for code-blocks executed later - especially those executed in other threads. It hides intent. This isn't the fault of the proposal, instead it's a fault of which part of the proposal to use. Besides I'm sure this would show up in code review before it made it into product right...

I think any of the proposals, BGGA, CICE, FCM, or my own C3S would equally work with the example given, basically people want something less verbose for implementing one method interfaces. The issue is what feels like Java and I would contend that BGGA doesn't. It has strange behaviour where the closure is like an object but not quite and needs two forms of boxing (closure conversion and RestrictedFunction) to get them to be objects. The syntax is also not Java like, Java doesn't use symbols it uses unabbreviated keywords, e.g. extends instead of :.