15-100 Lecture 4 (Thursday, May 22, 2008)

Files From Today's Class

From Classes to Objects

Last class, we created the Calculator class specification. But, a specification is, like a schematic or a blue print, just a descriptive document. We haven't yet created an actual calculator. So, let's talk about how to do that.

We're not going to build our calculator out of wood, plastic or metal. Instead, it is going to be a model constructed within the program. So, we need to ask Java to create the new calculator. We do this using Java's new operator, as follows:

  new Calculator();
  

The "new" operator allocates the storage for the Calculator and then uses the "constructor" specified within the Calculator class to initialize its instance variables and perform any other initialization. Once the new operator is done, a new Calculator, all ready to go, exists within the program.

In this case, the constructor doesn't happen to take any arguments, but if it did, they would be passed in within the ()-parentheses.

References and Reference Variables

Okay, so, we've created a new Calculator object, but how do we use it? In order to use an object, we need a reference to it. A reference is something we use to "refer to an object". In other words, it is something that we use to identify which object to use. In general, references are stored within reference variables and are accessed through those variables.

The new-operator gives us a reference to the newly created object. We can capture that reference into a variable by assigning it. Consider the code below:

  Calculator c;
  c = new Calculator();
  

The variable "c" is known as a reference variable because it stores a reference to the calculator. And, this is very important: It stores a reference to a Calculator, not the Calculator object, itself.

Please note that other intro sections confuse the details here. They make claims such as "c is an object" or "C is a Calculator". These claims are false. "c" denotes a variable capable of holding a reference to a calculator -- not a calculator. A reference is a simple, primitive value. The reference, itself, is not complex and cannot exhibit any behaviors -- it is simply read and assigned, just like an "int", "float", or "char".

Next class, we'll take a look at an example that makes it particularly clear that these variables are references to object, not objects themselves. It'll also make it clear that they are primitive values, not objects.

We manipulate an object via a reference to it via the "scope oeprator", which is a period. For example, "c.add();" asks the calculator to add. "c.enterNumber(6);" asks the calculator to enter the number 6 as input.

The "main" method
Okay. So, we know how to create class specs. And, we know how to turn those specs into objects. But, how does a program actually get started? This happens via a special method known as "main". When we start up Java, we give it the program and it runs the main() method. This method is static. In other words, it isn't the behaivor of an object, it is just floating out there by itself. Java actually runs it, rather than an object exhibiting it.

The main() method is the starting point. It will create the initial objects and get the program going. The main method always has exactly the same form. And, it is very important that it always takes the same form shown below. Java looks for a method exactly like this as the starting point. If the arguments don't match or the name doesn't match, it won't be recognized as the starting point. So, memorize this!

  public static void main(String[] args) {
    /*
     * Your code here
     */
  }
  

Notice the qualifer "static" -- you now know what this means. This means that this method isn't part of an object. Instead, it is just "floating". For the moment, I'd like to punt on "String[] args". In short, "String[]" represents a "String array", which is basically a list of Strings. We'll hit the details soon.

In class, we created the following main() method -- it does nothing more than create a new calculator and ask it to go through a few of its motions.

  public static void main(String[] args) {
    Calculator c = new Calculator();

    c.enterNumber(4);
    c.display();
    c.add();
    c.display();
    c.enterNumber(5);
    c.display();
    c.add();
    c.display();
    c.enterNumber(6);
    c.display();
    c.equals();
    c.display();
  }
  

Person vs. Machine: Closing the Gap

Next, I'd like to talk about how to actually get our program to run. But, before I do that, I want to provide some perspective about how our code interacts with the computer and the environment. This will help us to better understand the toos we use to make our program run and how they work.

When people write programs, they are doing it with a mind toward solving some real problem. They want to be concerned with the problem and its solution, not the details of the machine that is a tool for solving it.

For this reason, programmers usually write programs in English-like programming languages: C, C++, and our favorite, Java, for example. Although these languages are structured in a way that is useful to a computer, they are designed to be understandable and convenient for people.

Ultimately, a program written by a computer in one of these languages, a so-called High-Level Language is translated into another form that is better tailored for the machine. This new form is often known as an assembly language program or, in Java, byte code.

To help understand the difference, I like to think about a car with a driver and passenger. The passenger might give the driver directions:

Back out of the driveway and go right. Continue for 4 blocks. At the stop sign, make a right. Travel about 1/2 mile. You'll see a grocery store. The parking lot is on the right-hand side of the road, just past that grocery store. Park there.

The passenger provided a set of high-level instruction to the driver. These instructions were provided in a way that the driver understood and used commands that were descriptive in the context of the problem: Navigating the city en route to the grocery store.

But the car, the machine, can't understand these instructions. It requires instructions in a different language. The instructions might begin like this:

Press break pedal: Not less than 25 lbs of pressure. Push key into keyswitch, twist forward to on position; listen for click. Twist forward again with not less than 10 lbs of pressure. Listen for motor. Release keyswitch pressure. Slide gear selector down two notches into reverse. Reduce brake pressure to 5 lbs. Roll to bottom of driveway. Rapdily increase break pressure to not less than 25 lbs.

Etc. Etc. Etc.

The driver has to translate the high-level instructions provided by the passenger into a low-level (physical) language understood by the car. This language is coposed of much smaller steps. And, it might vary slightly from car to car. For example, the appropriate actions taken by the driver will be different for a car with a "standard" transmission than one with an "automatic" transmission. So, although the passenger's language is problem-oriented and car-independent, the driver's translation is car-oriented and car-specific.

The programming process happens in much the same way. Human programmers produce high-level directions in languages like Java. In this respect, we are acting like the passenger. These documents are then given to a program called a compiler that acts like the driver and translates them into a language appropriate for the machine.

The resulting program, which is machine specific, can run on only one type of computer, such as iMacs running OS X. This is why, when you go to the store, you have to buy different versions of the same program for different types of computers. The same high-level programs were compiled for different types of computer.

Java and the Virtual Machine

The designers of Java wanted to take a different approach. They wanted a programming system which was "compile once-run anywhere". In other words, they wanted one set of machine-oriented instructions to work on all computers.

This solution obviously can't work -- at least without something else entering the picture. Why not? Different computers understand different low-level instructions.

So, here's what they did. They invented a new type of computer, the Java Machine. And, they wrote a compiler that would convert Java high-level programs into low-level programs that would only run on this Java Machine.

But, they didn't build this machine in hardware. Instead they wrote a program to model it in software. Running this program creates the so-called Java Virtual Machine (JVM). The JVM was then compiled for many different types of physical computers. This software was then made available for many systems: It is part of the jdk that you might ahve downloaded to run java from home.

So, here's the Java model. The JVM is written and compiled for many different systems and is distributed widely. Java programmers compile software for the JVM. When one wants to run a Java program, one starts the JVM program and lets it run the compiled Java program.

Command-line Tools

We can compile this program using the Java compiler. It shouldn't be surprising that this program is named, javac. Here's how it works:
javac Calculator.java
If we look in the file system, we now see the byte-code -- the low-level program for the JVM. The byte code has the extension ".class".
ls Calculator.class

We can start java programs by providing the class name, without the extension, to the JVM. This is done, again no great surprise, with a program called "java" as follows:

java Calculator

The above example prints, as intended, the output of our Calculator's quick-and-dirty test program onto a console.

Making it Happen

The process used to create the "Calculator program" involved three steps: creating the Java program, compiling it, and starting it. If it had been a more complex program we might also have had to manage multiple pieces or debug mistakes.

In class, we went through and repeated the creation of the "Calculator program" using SubEthaEdit, javac, and java. Although we chose SubEthaEdit in class, any text editor that saves plain files will do. Just steer clear of things that don't save in plain text: Warning! Apple's simple text editor is one of these. Many folks like Dr. Java, Eclipse, or Blue Jay.

We compiled the program at the commandline: javac Calculator.java

Then, also from the command line, we ran it: java Calculator