. . . Mighty Coffee Beans Grow
Java is a descendant of the C programming language, which itself rose to celebrity from modest origins. C was developed in the 1970s by Dennis Ritchie of Bell Laboratories. At the outset it was closely associated with the Unix operating system; Unix was written in C, and the first C compilers ran under Unix. Soon the language spread to other systems. By now it has become so much a part of the mainstream that few remember just how idiosyncratic C once seemed. It is a language with a strict type system—the programmer must declare in advance what kind of data each variable can hold—and yet it allows many operations that other languages prohibit as reckless stunts. A prime example is the direct manipulation of "pointers," which represent the addresses of data items.
C has a distinctive, terse syntax, heavy on punctuation marks and symbols from the top row of the typewriter keyboard. Figure 2 gives an annotated example of what a very small C program looks like.
The main successor of C is C++, a language created in the 1980s by Bjarne Stroustrup, also of Bell Laboratories. The name is meant to suggest "C incremented," or "a little more than C." In fact it's a lot more—not just C+1 but maybe C x 2. The major addition is a facility for object-oriented programming, a technique first explored years earlier in some very different programming languages, such as Simula and Smalltalk.
Two main ideas lie behind object-oriented programming. First, programs are assembled not from separate data structures and procedures but from software "objects" that encapsulate both data and procedures. For example, a triangle object might include as data the coordinates of its three vertices and as procedures the methods for finding the triangle's center, area and altitude. The second idea is inheritance: Classes of objects are organized into a hierarchy extending from the general to the specific. The triangle might be a member of the class of polygons, from which it would inherit properties common to all polygons. At the same time the triangle class could be further specialized in subclasses for right triangles, equilateral triangles and so on.
On the surface, a C++ program looks just like one in C. But this similarity is deceptive; at the semantic level, algorithms in C++ require a thorough rethinking. Going from C to Java is similarly tricky. On the surface, again, Java also looks like the same old C, but underneath all is changed.
Like C++, Java is an object-oriented language. Indeed, the object methodology is enforced in Java, whereas the C++ programmer can fall back into standard C. On the other hand, Java is not a "pure" object language in the way that Smalltalk is. In Smalltalk, everything is an object, but in Java certain elementary data types, such as numbers and characters, do not have object status—they are not members of a class hierarchy.
Perhaps the most important change in going from C or C++ to Java is the abolition of pointers. A C program steps through the elements of an array by taking a pointer to the first element—the pointer is effectively the array’s address in memory—and repeatedly incrementing it. Java has a special form for accessing array elements without pointer arithmetic. Linked data structures in C also rely on pointers; in a list structure, for example, each item in the list includes a pointer to the next item, so that a program can step through the list by following the chain of pointers. Java provides for linked object references without exposing the machinery of pointers or addresses to the programmer.
Another major innovation in Java is automatic storage reclamation, otherwise known as garbage collection. If a C program allocates memory to a data structure, it had better remember to release the space once the structure is no longer needed, or all of the computer’s memory could be clogged with waste. Java programs automatically clean up after themselves. If an object is no longer needed, the garbage collector sweeps it up. (I speak of this mechanism as an innovation because it is new to the world of C-like languages, but Lisp systems have had garbage collection since about 1960.)
Two more notable features of Java are exceptions and threads. Exceptions are a means for gracefully handling run-time errors and other unexpected events. In many languages a simple routine for reading a disk file can become incomprehensible because the normal outcome (where the file is read successfully) is hidden in a thicket of statements needed to check for possible errors. (What if the file doesn't exist? What if it can't be opened? What if it ends prematurely?) Java programs clear up the clutter by "throwing" an exception to another routine, which "catches" it. (Just for the record, "catch" and "throw" are also Lisp concepts.)
Threads are a mechanism for dividing a program into multiple concurrent processes. For example, a program searching through a large database might start several threads, each one looking for a different key. Of course the threads will truly run at the same time only on a computer with multiple processors, but the Java virtual machine's scheduling algorithm simulates concurrency even on a single processor. Java's implementation of threads is admirably lucid.
A few cosmetic improvements in Java are also commendable. Java programs are not limited to the ASCII character set but are written in Unicode, which accommodates a broader selection of the world's (human) languages. Hence a constant can be named π instead of pi. Also, comments documenting Java programs can employ the tags of Hypertext Markup Language, so that the programs are easily formatted for readability with a Web browser.
Figure 3 gives the Java equivalent of the C program in Figure 2. It still has the same algorithmic core, but now that core is wrapped in a thick blanket of object-oriented fur.
All in all, Java seems a distinct improvement over C, and yet it is not the programming language I would choose to be stranded on a desert island with. Its strengths are directed to the needs of the professional software engineer; it is not so well adapted to the kind of exploratory or experimental programming whose aim is not to build a software product but merely to answer a question or calculate a value. (I suspect that a lot of computing in the sciences is of this nature.) Java also seems to me less than ideal as a medium for reasoning about algorithms, and for teaching some of the fundamental ideas of computer science. Not that it can’t be used for these purposes; it simply would not be my first choice.
A world where Java is the only programming language is therefore not a vision I greet warmly. But the prospect is not one that keeps me awake nights. One reason is that even if Java achieves its most grandiose ambitions—if it becomes the universal language of computing—it holds within itself the seed of a new confusion of tongues. That seed is the Java virtual machine.