James Gosling | Bulldozer00’s Blog
In this corner, we have Bjarne “No Yarn” Stroustrup, the father of C++. In the other corner, we have James “The Goose” Gosling, the father of Java. Ding, ding…… let’s get ready to ruuuumble!
“No Yarn” comes outs swinging and throws the first haymaker:
Well, the Java designers—and probably the Java marketers even more so—emphasized OO to the point where it became absurd. When Java first appeared, claiming purity and simplicity, I predicted that if it succeeded Java would grow significantly in size and complexity. It did. For example, using casts to convert from Object when getting a value out of a container (e.g., (Apple)c.get(i)) is an absurd consequence of not being able to state what type the objects in the container is supposed have. It’s verbose and inefficient. Now Java has generics, so it’s just a bit slow. Other examples of increased language complexity (helping the programmer) are enumerations, reflection, and inner classes. The simple fact is that complexity will emerge somewhere, if not in the language definition, then in thousands of applications and libraries. Similarly, Java’s obsession with putting every algorithm (operation) into a class leads to absurdities like classes with no data consisting exclusively of static functions. There are reasons why math uses f(x) and f(x,y) rather than x.f(), x.f(y), and (x,y).f()—the latter is an attempt to express the idea of a “truly object-oriented method” of two arguments and to avoid the inherent asymmetry of x.f(y).
In an agile counter move, “The Goose” launches a monstrous left hook:
These days we’re beating the really good C and C++ compilers pretty much always. When you go to the dynamic compiler, you get two advantages when the compiler’s running right at the last moment. One is you know exactly what chipset you’re running on. So many times when people are compiling a piece of C code, they have to compile it to run on kind of the generic x86 architecture. Almost none of the binaries you get are particularly well tuned for any of them. When HotSpot runs, it knows exactly what chipset you’re running on. It knows exactly how the cache works. It knows exactly how the memory hierarchy works. It knows exactly how all the pipeline interlocks work in the CPU. It knows what instruction set extensions this chip has got. It optimizes for precisely what machine you’re on. Then the other half of it is that it actually sees the application as it’s running. It’s able to have statistics that know which things are important. It’s able to inline things that a C compiler could never do. The kind of stuff that gets inlined in the Java world is pretty amazing. Then you tack onto that the way the storage management works with the modern garbage collectors. With a modern garbage collector, storage allocation is extremely fast.
On the age old debate about naked pointers, “The Goose” unleashes a crippling blow to the left kidney:
Pointers in C++ are a disaster. They are just an invitation to errors. It’s not so much the implementation of pointers directly, but it’s the fact that you have to manually take care of garbage, and most importantly that you can cast between pointers and integers—and the way many APIs are set up, you have to!
Enraged, “No Yarn” returns the favor with a rapid jab, jab, jab, uppercut combo:
Well, of course Java has pointers. In fact, just about everything in Java is implicitly a pointer. They just call them references. There are advantages to having pointers implicit as well as disadvantages. Separately, there are advantages to having true local objects (as in C++) as well as disadvantages. C++’s choice to support stack-allocated local variables and true member variables of every type gives nice uniform semantics, supports the notion of value semantics well, gives compact layout and minimal access costs, and is the basis for C++’s support for general resource management. That’s major, and Java’s pervasive and implicit use of pointers (aka references) closes the door to all that.
The “dark side” of having pointers (and C-style arrays) is of course the potential for misuse: buffer overruns, pointers into deleted memory, uninitialized pointers, etc. However, in well-written C++ that is not a major problem. You simply don’t get those problems with pointers and arrays used within abstractions (such as vector, string, map, etc.). Scoped resource management takes care of most needs; smart pointers and specialized handles can be used to deal with most of the rest. People whose experience is primarily C or old-style C++ find this hard to believe, but scope-based resource management is an immensely powerful tool and user-defined types with suitable operations can address classical problems with less code than the old insecure hacks.
Stunned silly, “The Goose” steps back, regroups, and charges back into the fray:
One of the most problematic (situations) over the years in C++ has been multithreading. Multithreading is very tightly designed into the code of Java and the consequence is that Java can deal with multicore machines very, very well.
“The Yarn” stands his ground and attempts to weather the ferocious onslaught:
The very first C++ library (really the very first C with classes) library, provided a lightweight form of concurrency and over the years, hundreds of libraries and frameworks for concurrent, parallel, and distributed computing have been built in C++. C++0x will provide a set of facilities and guarantees that saves programmers from the lowest-level details by providing a “contract” between machine architects and compiler writers—a “machine model.” It will also provide a threads library providing a basic mapping of code to processors. On this basis, other models can be provided by libraries. I would have liked to see some simpler-to-use, higher-level concurrency models supported in the C++0x standard library, but that now appears unlikely. Later—hopefully, soon after C++0x—we will get more libraries specified in a technical report: thread pools and futures, and a library for I/O streams over wide area networks (e.g., TCP/IP). These libraries exist, but not everyone considers them well enough specified for the standard.
And the winner is………?
So, do you think that I’ve served well as an impartial referee for this epic heavyweight battle? Hell, I hope not. I’m strongly biased toward C++ because it’s taken me years of study and diligent practice to become an intermediate-to-advanced C++ programmer (but still well below the skill level of the masters). I think that most Java programmer’s who religiously trash C++ do so out of fear of: its breadth+depth, its suitability for application at all layers of the stack, and the option to “get dangerously close to the machine“. On the other hand, C++ programmers who trash Java do so out of a sense of elitism and a disdain for object oriented purity.
Note: The snippets in this blarticle were copied and pasted from the delightful and engrossing “Masterminds Of Programming“. The book’s author, Federico Biancuzzi, not only picked the best possible people to interview, his questions were insightful and deeply thought provoking.