LESSON 1
Fundamentals of Java
Things we will study in class 1
The Origin of Java
Java Compared to C and C++
Java compared to C#
Java and its uses
Java’s contribution to the Internet
Java Applets
Security
Portability
The Bytecode
Setting up your Computer
Object Oriented Programming
Encapsulation
Polymorphism
Inheritance
Obtaining the Java Development Kit
Lesson 1
Fundamentals of Java Programming
The Origin of Java
Java was conceived by James Gosling, Patrick Naughton, Chris Warth, Ed Frank, and
Mike Sheridan at Sun Microsystems in 1991. This language was initially called “Oak” but was renamed “Java” in 1995.
Java compared to C and C++
Java is directly related to both C and C++. Java inherits its syntax from C. Its object model is adapted from C++. This makes it easy for a C/C++ programmer to learn Java and, conversely, for a Java programmer to learn C/C++.
The modern age of programming began with C. It moved to C++, and now to Java. By inheriting and building upon that rich heritage, Java provides a powerful, logically consistent programming environment that takes the best of the past and adds new features required by the online environment. Perhaps most important, because of their similarities, C, C++, and Java define a common, conceptual framework for the professional programmer.
Java compared to C#
Recently a new language called C# has come on the scene. Created by Microsoft to support its .NET Framework, C# is closely related to Java. In fact, many of C#’s features were directly adapted from Java. Both Java and C# share the same general C++-style syntax, support distributed programming, and utilize the same object model. There are, of course, differences between Java and C#, but the overall “look and feel” of these languages is very similar. This means that if you already know C#, then learning Java will be especially easy. Conversely, if C# is in your future, then your knowledge of Java will come in handy. But Java and C# are optimized for two different types of computing environments. Just as C++ and Java will co-exist for a long time to come, so will C# and Java.
Java and its Uses:
Programmers have accepted Java very quickly because it provides everything that is needed in a modern day language including:
Object-Oriented Features
Multithreading
Garbage Collection (Automatic Memory Management)
Networking and Security Features
Platform Independence (Architectural Neutral)
Internet/Web Development Features
It is somewhat similar to C++ and its support of popular object-oriented programming techniques make it easier for C and C++ programmers to quickly master Java’s powerful features.
Java’s Contribution to the Internet
The Internet helped Java emerge in the forefront of programming, and Java, in turn, has had a profound effect on the Internet. The reason for this is quite simple: In a network, there are two very broad categories of objects that are transmitted between the server and your personal computer: passive information and dynamic, active programs. For example, when you read your e-mail, you are viewing passive data. Even when you download a program, the program’s code is still only passive data until you execute it. However, a second type of object can be transmitted to your computer: a dynamic, self-executing program. Such a program is an active agent on the client computer, yet it is initiated by the server. For example, a program might be provided by the server to properly display the data that it is sending. As desirable as dynamic, networked programs are, they also present serious problems in the areas of security and portability. Prior to Java, cyberspace was effectively closed to half of the entities that now live there. As you will see, Java addresses those concerns and, in doing so, has defined a new form of program: the applet.
Java Applets
An applet is a special kind of Java program that is designed to be transmitted over the Internet and automatically executed by a Java-compatible Web browser. Furthermore, an applet is downloaded on demand, just like an image, sound file, or video clip. The important difference is that an applet is an intelligent program, not just an animation or media file. In other words, an applet is a program that can react to user input and dynamically change—not just run the same animation or sound over and over. As exciting as applets are, they would be nothing more than wishful thinking if Java were not able to address the two fundamental problems associated with them: security and portability. Before continuing, let’s define what these two terms mean relative to the Internet.
Security
As you are almost certainly aware, every time you download a “normal” program, you are risking a viral infection. Prior to Java, most users did not download executable programs frequently, and those that did, scan them for viruses prior to execution. Even so, most users still worried about the possibility of infecting their systems with a virus or allowing a malicious program to run wild in their systems. (A malicious program might gather private information, such as credit card numbers, bank account balances, and passwords by searching the contents of your computer’s local file system.) Java answers these concerns by providing a firewall between a networked application and your computer.
When using a Java-compatible web browser, it is possible to safely download Java applets without fear of viral infection. The way that Java achieves this is by confining a Java program to the Java execution environment and not allowing it access to other parts of the computer. Frankly, the ability to download applets with confidence that no harm will be done to the client computer is the single most important aspect of Java.
Portability
Many types of computers and operating systems are connected to the Internet. For programs to be dynamically downloaded to all of the various types of platforms, some means of generating portable executable code is needed. The same mechanism that helps ensure security also helps create portability. Java’s solution to these two problems is both elegant and efficient.
The Bytecode
The key that allows Java to solve both the security and the portability problems just described is that the output of a Java compiler is not executable code. Rather, it is bytecode. Bytecode is a highly optimized set of instructions designed to be executed by the Java run-time system, which is called the Java Virtual Machine (JVM). That is, the Java Virtual Machine is an interpreter for bytecode. This may come as a bit of a surprise. As you know, most modern languages, such as C++, are designed to be compiled, not interpreted—mostly because of performance concerns. However, the fact that a Java program is executed by the JVM help solves the major problems associated with downloading programs over the Internet. Here is why. Translating a Java program into bytecode makes it much easier to run a program in a wide variety of environments. The reason is straightforward: only the Java Virtual Machine needs to be implemented for each platform. Once the run-time package exists for a given system, any Java program can run on it. Remember that although the details of the JVM will differ from platform to platform, all understand the same Java bytecode. If a Java program were compiled to native code, then different versions of the same program would have to exist for each type of CPU connected to the Internet. This is, of course, not a feasible solution. Thus, the interpretation of bytecode is the easiest way to create truly portable programs.
The fact that a Java program is interpreted also helps make it secure. Because the execution of every Java program is under the control of the JVM, the JVM can contain the program and prevent it from generating side effects outside the system. Safety is also enhanced by certain restrictions that exist in the Java language. When a program is interpreted, it generally runs substantially slower than the same program would run if compiled to executable code. However, with Java, the differential between the two is not so great. The use of bytecode makes it possible for the Java run-time system to execute programs much faster than you might expect. Although Java was designed for interpretation, there is technically nothing about Java that prevents on-the-fly compilation of bytecode into native code. For this reason, Sun began supplying its HotSpot technology not long after Java’s initial release. HotSpot provides a JIT (Just In Time) compiler for bytecode. When a JIT compiler is part of the JVM, it compiles bytecode into executable code in real time, on a piece-by-piece, demand basis. It is important to understand that it is not possible to compile an entire Java program into executable code all at once because Java performs various checks that can be performed only at run time. Instead, the JIT compiles code as it is needed, during execution. Furthermore, not all sequences of bytecode are compiled—only those that will benefit from compilation. The remaining code is simply interpreted. The just-in-time approach still yields a significant performance boost, though. Even when dynamic compilation is applied to bytecode, the portability and safety features will still apply, because the run-time system (which performs the compilation) will still be in charge of the execution environment.
Object-Oriented Programming
At the center of Java is object-oriented programming (OOP). The object-oriented methodology is inseparable from Java, and all Java programs are, to at least some extent, object-oriented. Because of OOP’s importance to Java, it is useful to understand OOP’s basic principles before you write even a simple Java program.
OOP is a powerful way to approach the job of programming. Programming methodologies have changed dramatically since the invention of the computer, primarily to accommodate the increasing complexity of programs. For example, when computers were first invented, programming was done by toggling in the binary machine instructions using the computer’s front panel. As long as programs were just a few hundred instructions long, this approach worked. As programs grew, assembly language was invented so that a programmer could deal with larger, increasingly complex programs, using symbolic representations of the machine instructions. As programs continued to grow, high-level languages were introduced that gave the programmer more tools with which to handle complexity. The first widespread language was, of course, FORTRAN. Although FORTRAN was a very impressive first step, it is hardly a language that encourages clear, easy-to-understand programs.
The 1960s gave birth to structured programming. This is the method encouraged by languages such as C and Pascal. The use of structured languages made it possible to write moderately complex programs fairly easily. Structured languages are characterized by their support for stand-alone subroutines, local variables, rich control constructs, and their lack of reliance upon the GOTO. Although structured languages are a powerful tool, even they reach their limit when a project becomes too large.
Consider this: At each milestone in the development of programming, techniques and tools were created to allow the programmer to deal with increasingly greater complexity. Each step of the way, the new approach took the best elements of the previous methods and moved forward. Prior to the invention of OOP, many projects were nearing (or exceeding) the point where the structured approach no longer works. Object-oriented methods were created to help programmers break through these barriers.
Object-oriented programming took the best ideas of structured programming and combined them with several new concepts. The result was a different way of organizing a program. In the most general sense, a program can be organized in one of two ways: around its code (what is happening) or around its data (what is being affected). Using only structured programming techniques, programs are typically organized around code. This approach can be thought of as “code acting on data.”
Object-oriented programs work the other way around. They are organized around data, with the key principle being “data controlling access to code.” In an object-oriented language, you define the data and the routines that are permitted to act on that data. Thus, a data type defines precisely what sort of operations can be applied to that data.
To support the principles of object-oriented programming, all OOP languages, including Java, have three traits in common: encapsulation, polymorphism, and inheritance.
Encapsulation
Encapsulation is a programming mechanism that binds together code and the data it manipulates, and that keeps both safe from outside interference and misuse. In an object-oriented language, code and data can be bound together in such a way that a self-contained black box is created. Within the box are all necessary data and code. When code and data are linked together in this fashion, an object is created. In other words, an object is the device that supports encapsulation.
Within an object, code, data, or both may be private to that object or public. Private code or data is known to and accessible by only another part of the object. That is, private code or data cannot be accessed by a piece of the program that exists outside the object. When code or data is public, other parts of your program can access it even though it is defined within an object. Typically, the public parts of an object are used to provide a controlled interface to the private elements of the object.
Java’s basic unit of encapsulation is the class. Although the class will be examined in great detail later in this book, the following brief discussion will be helpful now. A class defines the form of an object. It specifies both the data and the code that will operate on that data. Java uses a class specification to construct objects. Objects are instances of a class. Thus, a class is essentially a set of plans that specify how to build an object.
The code and data that constitute a class are called members of the class. Specifically, the data defined by the class are referred to as member variables or instance variables. The code that operates on that data is referred to as member methods or just methods. Method is Java’s term for a subroutine. If you are familiar with C/C++, it may help to know that what a Java programmer calls a method, a C/C++ programmer calls a function.
Polymorphism
Polymorphism (from the Greek, meaning “many forms”) is the quality that allows one interface to access a general class of actions. The specific action is determined by the exact nature of the situation. A simple example of polymorphism is found in the steering wheel of an automobile. The steering wheel (i.e., the interface) is the same no matter what type of actual steering mechanism is used. That is, the steering wheel works the same whether your car has manual steering, power steering, or rack-and-pinion steering. Therefore, once you know how to operate the steering wheel, you can drive any type of car.
The same principle can also apply to programming. For example, consider a stack (which is a first-in, last-out list). You might have a program that requires three different types of stacks. One stack is used for integer values, one for floating-point values, and one for characters. In this case, the algorithm that implements each stack is the same, even though the data being stored differs. In a non-object oriented language, you would be required to create three different sets of stack routines, with each set using different names. However, because of polymorphism, in Java you can create one general set of stack routines that works for all three specific situations. This way, once you know how to use one stack, you can use them all.
More generally, the concept of polymorphism is often expressed by the phrase “one interface, multiple methods.” This means that it is possible to design a generic interface to a group of related activities. Polymorphism helps reduce complexity by allowing the same interface to be used to specify a general class of action. It is the compiler’s job to select the specific action (i.e., method) as it applies to each situation. The programmer does not need to do this selection manually. What he has to do is remember and utilize the general interface.
Inheritance
Inheritance is the process by which one object can acquire the properties of another object. This is important because it supports the concept of hierarchical classification. If you think about it, most knowledge is made manageable by hierarchical (i.e., top-down) classifications.
For example, a Red Delicious apple is part of the classification apple, which in turn is part of the fruit class, which is under the larger class food. That is, the food class possesses certain qualities (edible, nutritious, etc.) which also, logically, apply to its subclass, fruit. In addition to these qualities, the fruit class has specific characteristics (juicy, sweet, etc.) that distinguish it from other food. The apple class defines those qualities specific to an apple (grows on trees, not tropical, etc.). A Red Delicious apple would, in turn, inherit all the qualities of all preceding classes, and would define only those qualities that make it unique.
Without the use of hierarchies, each object would have to explicitly define all of its characteristics. Using inheritance, an object need only define those qualities that make it unique within its class. It can inherit its general attributes from its parent. Thus, it is the inheritance mechanism that makes it possible for one object to be a specific instance of a more general case.
Obtaining the Java Development Kit
Now that the theoretical underpinning of Java has been explained, it is time to start writing Java programs in your next class (class 2). Before you can compile and run those programs, however, you must have a Java development system installed on your computer. The one used by this book is the standard JDK (Java Development Kit), which is available from Sun Microsystems. Several other Java development packages are available from other companies, but we will be using the JDK because it is available to all readers. It also constitutes the final authority on what is and isn’t proper Java. We will be using J2SE 5 (or later) to compile and run the programs listed in this course.
The JDK can be downloaded free of charge from www.java.sun.com. You will just have to go to the download page and follow the instructions for the type of computer that you have. After you have installed the JDK, you will be ready to compile and run programs. The JDK supplies two primary programs. The first is javac.exe, which is the Java compiler. The second is java.exe, which is the standard Java interpreter, and is also referred to as the application launcher. One other point: the JDK runs in the command prompt environment. It is not a windowed application.
* * * * * * * * * * *