Welcome to Cafe Au Lait

What Is Cafe Au Lait?

What is Cafe Au Lait? There are several meanings.
  1. A form of coffee served in New Orleans, generally cut with chicory and large quantities of milk. Goes well with beignets.
  2. A web site devoted to Java at http://sunsite.unc.edu/javafaq/
  3. This newsletter
It's the third definition that concerns us now. This is the first of an occasional series of newsletters in which I intend to ramble on about various topics related to Java, the Internet, programming, genealogy, mathematics and whatever else crosses my mind. There's no particular periodicity to these missives. They arrive when I feel like sending them. This list is low-volume, one-way. There should be no more than one message a week (at most!) from this list. It is moderated and I am the only one who can post to it.

I haven't settled on a definite format for these newsletters yet, but each one will probably include some brief comments, recent news about Java, perhaps some reader responses, and one major article about something that interests me. The main form of distribution will be the Cafe Au Lait mailing list, but they'll also be available at the Cafe Au Lait web site, http://sunsite.unc.edu/javafaq/newsletter/.

Who am I?

My name is Elliotte Rusty Harold. In so-called real life I'm a writer, currently residing in the East Village of New York City, with my wife, Beth Anderson, and our cat, Possum. In previous lives I've worked in web publishing, solar astronomy, and applied mathematics.

Currently I've got several books about Java in varying stages of development. The Java Developer's Resource is an introduction to Java for programmers. It's just been published by Prentice Hall Professional Technical Reference and should be in stores now. (ISBN: 0-1357-0789-7) I'll write more about the others as they're released.

I also maintain several websites including Cafe Au Lait at http://sunsite.unc.edu/javafaq/ and The Well Connected Mac at http://www.macfaq.com/. Lately I've had a number of interesting ideas that I wanted to write about, but that did not fit well into either a book or a website. Hence this mailing list. We kick off the list with an article explaining why Java and C++ are different. There've been probably hundreds of articles explaining how Java and C++ are similar and how they're different at a very low level. This article attempts to show why Java and C++ are different. It relies heavily on one of the more fascinating books I've read lately, The Design and Evolution of C++, by Bjarne Stroustrup. If you're one of the many who's under the illusion that C++ and Java are very similar, this book should really open your eyes. Java and C++ are both object oriented languages with a passing similarity to C, but that's where the resemblance ends. This book tells you why C++ is the way it is. It demonstrates conclusively that the experiences and decisions that influenced C++ are vastly different from those that influenced Java.

Recent Releases

September has been a busy month for Javasoft. They've released version 0.95 of the object serialization specification (http://chatsubo.javasoft.com/prebeta1/serial-prebeta1.ps), draft 0.35 of the Java Beans specification (http://www.javasoft.com/beans/) and Jeeves Alpha 1.2 (http://www.javasoft.com/jeeves/CurrentRelease/).

They've also unveiled the Java Developer Connection. Once the fluff is cleared away it looks like a way to get you to prepay for five technical support incidents at $99 per incident, $495 total. This may be reasonable if you need the support. Otherwise I'd pass. Everything else they offer is available for free.

http://javasoft.usec.sun.com/

Finally Han peter van Vliet has rereleased Mocha, a Java decompiler. If you missed it the first time around, download it now from http://web.inter.nl.net/users/H.P.van.Vliet/mocha.html

The Design and Evolution of C++

Lately I've been reading a fascinating book by Bjarne Stroustrup, the inventor of C++. It's called The Design and Evolution of C++. It details the history of C++ and how it came to be what it is today, with emphasis on why the decisions that were made about the language were made. What's most interesting to me is how this contrasts with Java. One of the things a Java programmer will learn from this book is just how different Java and C++ really are, despite superficial similarities.

Stroustrup's Life Experience

Chapter 1, The Prehistory of C++, describes Stroustrup's early experience with Simula and BCPL on his Ph.D thesis. This went a long way toward determining the basic requirements for C++. Stroustrup was writing operating system simulators in Simula on an IBM 360/165 mainframe. He liked Simula's classes. However he found that the program was excessively slow, and that garbage collection took over 80% of CPU time. He eventually had to rewrite the program in BCPL, a precursor to C, to get acceptable performance. This experience led him to define three key requirements for the programming language he wanted:
  1. The language would have to have classes, concurrency and strong type checking. This is where BCPL was lacking.
  2. The language would have to run programs as fast as BCPL. This was where Simula is lacking.
  3. The language should be highly portable. In particular "There should be no complicated runtime support system to port."(Stroustrup, p. 21) As you'll see, this is one of the areas in which Java is lacking.
The first goal was shared by Java. The second two were not. In Stroustrup's grad student days, computers were quite slow. Today CPU speeds are phenomenal, and it's permissible to trade execution speed for ease of programming. Java does exactly this. Furthermore compiler technology has improved to the point where a language does not need to be as close to the hardware as BCPL, C, or C++ to get maximum performance. Java is quite removed from most hardware.

On the third point Java is even more different from C++. Java has a very complicated runtime system that is growing more complicated every month. This makes ports to new operating systems quite difficult. C++'s portability boundary is essentially a C compiler. Porting Java requires much more work.

Furthermore the sorts of programs Stroustrup was writing were probably the majority of computer programs written and run in 1979, but are no longer so in 1996. In 1979 almost everyone who actually used a computer was a programmer. Therefore ease of use for programmers was paramount. Today the personal computer revolution has made end-users who do not program the vast majority. Ease of use for end-users is more important than ease of use for programmers. Given the different time frames and life histories of the people who created C++ and Java it really shouldn't be surprising that they produced such different languages.

The First C++

Chapter 2, C with Classes, describes the progenitor of C++. This chapter shows the first of several places where C++ and Java diverged. Stroustrup made a conscious decision before beginning implementation to keep the language minimal by avoiding direct support for threading, strings, complex numbers, abstract data structures, and many other features. The idea was that these would be implemented as separate libraries, and indeed they were.

Java, however, had these (except for complex numbers) from the start. Although these are part of the java.lang library, this library is required to be a part of all Java implementations and is a critical part of Java. This in contrast to the many different libraries available for C++ that fulfill the same functions.

The second goal for C with Classes was to allow it to be used wherever C was. Java took a different route. C is a very good language for systems programming, and another C is not needed. C++ attempted to replace C. Java does not do this. Therefore it can be better at what it is intended for, secure, safe, application programming.

There were two primary reasons Stroustrup decided to make C with Classes a superset of C. One was that it was relatively easy to implement C with Classes via a preprocessor that turned C with Classes code into C code. The other was that "Having C as a subset dramatically reduced the support and documentation work needed." (p. 30). Since Stroustrup initially did all work on both the C with Classes implementation and documentation himself, reducing the burden on the language designer was crucial.

Java was created not as a superset of C, but with the intent of being familiar to the existing base of C programmers. However the compiler was never implemented as a preprocessor that produced C code. Furthermore, Java had a team of people and still needed over a year from initial release before adequate documentation was available. While Javasoft may be understaffed, it has always had at least several people working on the project.

In short, C++ had to be minimal superset of C in order to make it a manageable project for one programmer, Stroustrup. Even in the early days, however, Sun always had at least a few programmers and support staff working on Java, so the path of least resistance did not always have to be taken.

Making It Explicit

Chapter 4 is titled "C++ Language and Design Rules". It describes Stroustrup's overall view that guided the design of C++, and it is here that the differences and similarities between Java and C++ are most apparent. According to Stroustrup the fundamental aims of C++ are fourfold:

Java does share these broad aims with C++. It is arguably more successful with the first than C++. I know very few programmers who enjoy C++. I know at least a few who enjoy Java. Both C++ and Java meet the next three aims. So in these general aims C++ and Java are quite similar. It's in the specific implementations of these goals that Java and C++ diverge. Stroustrup divides the rules that C++ should adhere to into four categories: general rules, design support rules, language technical rules, and low-level programming support rules.

Stroustrup's general rules for C++ are eightfold, most of which are shared by Java. To quote:

C++'s evolution must be driven by real problems. Anyone who reads the programmer newsgroups of Usenet is more than familiar with the phenomenom of "too many people searching for a problem to apply their pet solution to" (p. 110). Sometimes this solution is proving program correctness; sometimes it's fixed point arithmetic; sometimes it's multiple inheritance. To be genuinely useful a language must solve real problems, not merely implement the latest hot technique from academia. To be successful a language should be more concerned with the day-to-day problems of working programmers than with grad-school abstractions. Java and C++ share this philosophy. Java, though, has the advantage of ten years more experience than C++ in seeing what is in fact a real solution to a problem and what is only apparently so. Operator overloading and multiple inheritance, to name just the two most notorious examples, are far more popular among grad-school hot dogs than among working programmers. In the real world they've proven neither necessary nor useful outside of carefully constructed textbook examples.

Don't get involved in a sterile quest for perfection. No language can be right for all problems. Different programs require different tools. Java, even more than C++, deliberately limits the domain of problems for which it is suited. That domain is quite large, but still finite. Java, even more than C++, does not see itself as the solution to all programming problems. By restricting the domain in which its applicable (essentially by removing systems programming from that domain) Java can be made better for the domains that remain.

C++ must be useful now. C++ needed to be useful immediately. It could not only run on a few systems with scads of memory, programmed by superlative programmers. Java is exactly the same. The difference here is the definition of now. When C++ was invented now meant a 286 (more likely an 8088) with maybe a megabyte of RAM. In fact even that was underpowered, and C++ was targeted at minicomputers rather than personal computers. Ten years later, Java can safely assume a 486 with 16 megabytes of RAM, or something even faster. Features that had to be tossed to make C++ useful now (in 1984) were no-brainers to add to Java now (1994).

Every feature must have a reasonably obvious implementation. The resources simply were not available to implement truly complicated algorithms in the compiler. I'm not sure whether Java follows this rule or not. Any thoughts from people who were involved in the Green Project? Was the time required to implement features a serious consideration in language design?

Always provide a transition path. Compatibility with both C and older versions of C++ had to be maintained. Java tossed this one out the window. It has no compatibility with C or C++, and compatibility with earlier versions of Java has been broken several times. While this allows the language to evolve more quickly, it is a clear problem for Java developers. It is likely that the speed at which Java is being adopted may cause more problems in the future. This one's a clear advantage for C++ in and of itself, but is simultaneously responsible for many obvious problems with the language.

C++ is a language, not a complete system. What Stroustrup means by this is that C++ should allow for multiple IDE's and yet not require any. Java follows this model well. However there's another point Stroustrup doesn't refer to here, but which may appear in the minds of many readers. Java, especially with the virtual machine and network computers, almost appears to be an operating system. This is clearly not true of C++. C++ is much easier to port to a new system than is Java.

Provide comprehensive support for each supported style. C++ should not be limited to one style of object-oriented analysis and design; or, for that matter, even to object-oriented programs. Not all programmers program the same way, nor should they. Java supports this. It is broad enough to support many different styles, while not requiring any.

Don't try to force people. Programmers are smart people, and should not be constrained to do only what is right. Here Java diverges wildly from C++. Given the restricted domain in which Java lives, it was decided very early on to make it far harder to shoot yourself in the foot with Java than with C++. Programmers may be smart people, but often that only means they can find more intricate ways to shoot their feet. Java wisely decided to remove a lot of power from the language in the form of pointer arithmetic and memory allocation and deallocation. Very little was lost by making the language safer, and much was gained.

Overall we see that six of Stroustrup's eight general rules are followed by Java. More than half of these are better implemented in Java than in C++. This accounts in large part for Java's rapid acceptance in the object community. The two that are not implemented by Java are the requirement of compatibility with C, and the provision of enough rope to programmers to allow them to hang themselves.

Stroustrup next proffers six design support rules. According to Stroustrup these "relate primarily to C++'s role in supporting design based on the notions of data abstraction and object oriented programming." (p. 114). The rules are:

Java supports all of these except the fifth. Once again Java has chosen simplicity and object design, but prefers to enforce safety rather than relying on programmer skill.

Support sound design notions. In other words, C++ should allow object oriented programs. The language should provide facilities for data abstraction and other object oriented techniques which are difficult to achieve in C. In the early 1980s this was a radical innovation. Now it's widely accepted. Java and C++ both support object oriented design more or less equally.

Provide facilities for program organization. C++ is supposed to help "organize programs to be easier to write, read, and maintain." (p. 115). In large part C++ has failed at this, primarily because of Stroustrup's desire to keep low-level syntax very close to C's. On the micro-level Java code is far easier to read than C++ code. Whether Java also produces more maintainable code in the long-term remains to be seen. There simply is not yet a large enough experience base with large, long-term, Java programs.

Say what you mean. The language should be closer to what programmers say to each other than what the compiler says to the machine. Meaning should not be hidden in a "mess of bits, bytes, pointers, loops" (p. 115). C++, although an improvement on C in this regard, still leaves much to be desired. Pointers, in particular, lead to exceptionally obtuse code. Java has wisely removed this. It is in general easier to "say what you mean" in Java than in C++.

All features must be affordable. No matter how convenient a feature is to programmers, it's pointless if it makes the final executable excessively slow or large. Java shares this philosophy in principle. In practice the passage of time has made many features such as garbage collection more affordable than they were when Stroustrup was designing C++.

It is more important to allow a useful feature than to prevent every misuse. "A systems programming language cannot prevent a determined programmer from breaking the system...rules are not intended as protection against deliberate violation" (p. 116). However, Java requires security at its core. It must protect against deliberate and malicious violation. This doesn't mean Stroustrup is wrong. He's not. What it means is that Java is not suitable for systems programming.

Support composition of software from separately developed parts. This serves to help programmers efficiently and quickly build working systems. Java clearly shares this goal with C++ (and with every other object oriented language on the planet).

The language technical rules are concerned with the lower level syntax rather than the design of programs. There are seven of these rules:

No implicit violations of the static type system. This is a way of saying that C++ is strongly typed. Casts must be made explicitly. Java is even more severe about this than C++. Though neither Java nor C++ can detect all unsafe casts at runtime, Java will detect bad casts at runtime. C++ does not (short of a system crash).

Provide as good support for user-defined types as for built-in types. Java and C++ both support this though in different ways. C++'s support is probably slightly more complete due to operator overloading, but that's a tradeoff I'm willing to accept.

Locality is good. Implementation should be separated from declaration. Java is even stronger than C++ in this regard since private members and local variables cannot be accessed, even by outright deceit.

Avoid order dependencies. Moving declarations and definitions aruond in a source code file shouldn't effect the final executable in any language. however in many older languages it does. Both C++ and Java wisely allow classes and methods to be declared in any order that's convenient for the programmer.

If in doubt, pick the variant of the feature that is easiest to teach. Java was designed to be easy to teach. The importance of making a language easy to learn was frontmost in the minds of Java's designers. It was only a tie-breaker for C++. Ease of learning was perhaps less important for C++ than Java since teachers could fall back on what programmers already knew of C.

Syntax matters (often in perverse ways). It is important to make the language familiar to the existing base of programmers who are loath to change the way they write code. C++ maintains compatibility with C. Java only attempts to retain famliarity with C.

Preprocessor usage should be eliminated. C++ tries to do this by making the preprocessor unnecessary, for example through const. Java eliminates preprocessor usage by eliminating the preprocessor. I think Java's method is more direct and successful. Of course here as elsewhere C++ is constrained by the need for compatibility with C.

Finally Stroustrup elaborates five rules for supporting low-level programming. Since Java isn't intended to support low-level programming like C does, it's no surprise that Java and C++ differ widely here. These five rules are:

Use traditional (dumb) linkers. A port of C++ should only require a port of the compiler. In particular you should not need to port the linker too. Java doesn't have a traditional linker, but it clearly fails in this goal. This is one of the few areas where Java is fundamentally inferior to C++. Porting Java requires substantially more effort than porting C++.

No gratuitous incompatibilities with C. Java shares this philosophy. It just has a somewhat more conservative definition of "gratuitous." Java changes much C syntax that's clearly caused problems over the years, for instance allowing assignment statements to appear where one would normally expect a comparison. C++ only changes that C syntax that's necessary to support C++'s new features. It does not attempt to fix mistakes made in the design of C.

Leave no room for a lower level language below C++ (except assembler). Here Java differs from C++. There is room for a language between the abstraction level of Java and that of assembler. Typically this is something like C or C++. Java can afford the higher level of abstraction because it is not intended for systems programming.

What you don't use, you don't pay for (the zero-overhead rule). If you don't use a feature it shouldn't make your code slower. Java aspires to this. Time will tell whether it has succeeded as well as C++.

If in doubt, provide means for manual control. Stroustrup doesn't want to rely on advanced compilers to handle optimizations and layout in memory. This is a common character trait of C programmers, especially thoes trained in the 1980s and earlier. But the fact is, compiler and optimization technology has gotten much better in the last ten years, and on modern RISC architectures decent compilers can easily outperform human tuning. While it's possible to believe that a few human experts might be able to outperform the compiler on one system, there's little chance anyone can do it on all the systems where Java runs.

That pretty much wraps up the broader issues that informed the design of C++. The remainder of the book is mostly concerned with the ANSI standardization process and various fairly low-level details of C++. Neither topic is immediately relevant to Java programmers. Let's end by summarizing the reasons why Java is so different from C++:

That's why Java and C++ are different. How are they similar?

The first is a requirement for any object-oriented language. So how similar are C++ and Java really? If you pull away the similarities common to all good object-oriented languages, the answer is "Not Very." So the next time some professional C++ hater derides Java as nothing more than warmed-over C++, you know what you can tell them.

This doesn't completely describe the fundamental differences between Java and C++. This article's taken the issue up from the perspective of C++'s history. A close look at Java's history, particularly its original target market of consumer appliances would reveal a host of other differences. In particular Java is based on an entire runtime supprt system which is foreign to C++; but that's a story for another day. Even viewed purely as programming languages, with no reference to the systems on which they run, Java and C++ are fundamentally different languages. They are similar only on the surface.


Stroustrup, Bjarne, The Design and Evolution of C++, New York: Addison-Wesley, 1994, ISBN: 0-201-54330-3

Subscription Instructions

To subscribe to this newsletter send email to listproc@listserv.oit.unc.edu from the account you want to receive mail from with the following text only in the BODY of your message (NOT the subject.)
SUBSCRIBE cal FirstName LastName
You should of course replace FirstName and LastName with your real first name and last name though I won't be particularly bothered if you wish to use an alias.

To unsubscribe from the list send email to listproc@educom.unc.edu from the account you wish to unsubscribe with the following line in the BODY of your message (NOT the subject.)

unsubscribe cal
To get more information on how to use this service, please send the command HELP in a line by itself in a mail message to listproc@educom.unc.edu.

You MUST follow these instructions. The list owner will not subscribe or unsubscribe you manually if you do not follow these instructions. Requests to do so will be ignored. Repeated requests will get you dumped in my kill file.


Back Issues

[ Cafe Au Lait | Books | Training | Links | FAQ | Tutorial | User Groups ]


Copyright 1996 Elliotte Rusty Harold
elharo@sunsite.unc.edu
Last Modified October 8, 1996