Additionally, keeping track of what must be recompiled when a declaration changes somewhere else strains the capabilities of development tools--even fancy "make"-style tools such as found on UNIX systems. This development approach bogs down as the code bases of applications grow to hundreds of thousands of lines.
Better methods of fast and fearless prototyping and development are needed. The Java language environment is one of those better ways, because it's interpreted and dynamic.
As discussed in the previous chapter on architecture-neutrality, the Java compiler generates byte codes for the Java Virtual Machine[3], which was introduced briefly in Chapter 4. The notion of a virtual interpreted machine is not new. But the Java language brings the concepts into the realm of secure, distributed, network-based systems.
The Java language virtual machine is a strictly defined virtual machine for which an interpreter must be available for each hardware architecture and operating system on which you wish to run Java language applications. Once you have the Java language interpreter and run-time support available on a given hardware and operating system platform, you can run any Java language application from anywhere, always assuming the specific Java language application is written in a portable manner.
The notion of a separate "link" phase after compilation is pretty well absent from the Java environment. Linking, which is actually the process of loading new classes by the Class Loader, is a more incremental and lightweight process. The concomitant speedup in your development cycle means that your development process can be much more rapid and exploratory, and because of the robust nature of the Java language and run-time system, you will catch bugs at a much earlier phase of the cycle.
Object-oriented programming has become accepted as a means to solve at least a part of the "software crisis", by assisting encapsulation of data and corresponding procedures, and encouraging reuse of code. Most programmers doing object-oriented development today have adopted C++ as their language of choice. But C++ suffers from a serious problem that impedes its widespread use in the production and distribution of "software ICs". This defect is known as the fragile superclass problem.
Finally, the storage layout of objects is not determined by the compiler. The layout of objects in memory is deferred to run time and determined by the interpreter. Updated classes with new instance variables or methods can be linked in without affecting existing code.
At the small expense of a name lookup the first time any name is encountered, the Java language eliminates the fragile superclass problem. Java programmers can use object-oriented programming techniques in a much more straightforward fashion without the constant recompilation burden engendered by C++. Libraries can freely add new methods and instance variables without any effect on their clients. Your life as a programmer is simpler.
Class
, instances of which contain run-time class definitions. If you're handed an object, you can find out what class it belongs to. In a C or C++ program, you may be handed a pointer to an object, but if you don't know what type of object it is, you have no way to find out. In the Java language, finding out based on the run-time type information is straightforward. It is also possible to look up the definition of a class given a string containing its name. This means that you can compute a data type name and easily have it dynamically-linked into the running system.
The Java(tm) Language Environment: A White Paper