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/.
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.
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.
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
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.
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.
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.
- Make Programming a more enjoyable experience for serious programmers
- Be a better C
- Support Data Abstraction
- Support object-oriented programming
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.
- C++'s evolution must be driven by real problems.
- Don't get involved in a sterile quest for perfection.
- C++ must be useful now.
- Every feature must have a reasonably obvious implementation.
- Always provide a transition path.
- C++ is a language, not a complete system.
- Provide comprehensive support for each supported style.
- Don't try to force people.
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.
- Provide facilities for program organization.
- Say what you mean.
- All features must be affordable.
- It is more important to allow a useful feature than to prevent every misuse.
- Support composition of software from separately developed parts.
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).
- No implicit violations of the static type system.
- Provide as good support for user-defined types as for built-in types.
- Locality is good.
- Avoid order dependencies.
- If in doubt, pick the variant of the feature that is easiest to teach.
- Syntax matters (often in perverse ways).
- Preprocessor usage should be eliminated.
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++.
- Use traditional (dumb) linkers.
- No gratuitous incompatibilities with C.
- Leave no room for a lower level language below C++ (except assembler).
- What you don't use, you don't pay for (the zero-overhead rule).
- If in doubt, provide means for manual control.
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++:
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.
SUBSCRIBE cal FirstName LastNameYou 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 email@example.com from the account you wish to unsubscribe with the following line in the BODY of your message (NOT the subject.)
unsubscribe calTo get more information on how to use this service, please send the command HELP in a line by itself in a mail message to firstname.lastname@example.org.
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.
[ Cafe Au Lait | Books | Training | Links | FAQ | Tutorial | User Groups ]