When you use a variable name in a method call, it _____ as the variable in the method header.

Try the new Google Books

Check out the new look and enjoy easier access to your favorite features

When you use a variable name in a method call, it _____ as the variable in the method header.

Try the new Google Books

Check out the new look and enjoy easier access to your favorite features

When you use a variable name in a method call, it _____ as the variable in the method header.

4. Although the terms parameter and arguments are closely related, the difference between them is that "argument" refers to ____________________. a. a passed constant b. a value in a method call c. a formal parameter

d. a variable that is local to a method

  For a concrete example, let's see how to write a call frame for the min method definition, being called as Math.min(x,y+1). First, the parameter mechanism in Java is called copy by value. With copy by value, Java copies the value of each argument (arguments are evaluated when a method is called, at its call site) into a parameter variable: pictured, as always, a box labeled by its parameter's name and type. So, parameters are just special kinds of variables: each is always initialized by the value of it matching argument from the call site.
When you use a variable name in a method call, it _____ as the variable in the method header.

  There are no local variables here, so we leave blank that part of the call frame. After the call frame has been specified, and the parameters have been initialized, Java executes the body of the method, which refers to the parameters to compute its value. The result is that this method returns 5, which replaces the method call at the call site, in the System.out.println statement, so ultimately 5 is printed on the console.

For another example, here is a call frame for the factorial method Note that after it returns to the call site, the value that it returns as a result is stored into the variable y.

When you use a variable name in a method call, it _____ as the variable in the method header.

  Besides its single parameter, this method declares two local variables (answer and i, the for loop index variable), which are initialized in their declarations to 1 and 2 respectively when Java executes the body of its method. Note how state changes to variable are illustrated: crossing out the old value and writing the new value after it.
Advanced Call Frames In this section, we will explore call frames in a bit more detail, looking closely at the difference between changing the state of a variable and changing the state of an object (referred to by a variable). Let's start by hand simulating a call to the following method public static void swap (int a, int b) { int temp = a; a = b; b = temp; } Let's assume that this method is defined in a class named Utility and that we declare int x=5, y=8; and call Utility.swap(x,y); what values are ultimately stored in x and y? Are these variables swapped, or do they remain unchanged? The call frame shows us.

IMPORTANT: If we do not execute a return; statement in a void method (there is none in the code below), Java automatically does the equivalent of return; when it reaches the end of the block that is the body of the method. Java DOES NOT allow an implicit return in a non-void method, becuase we MUST specify an expression that tells Java what value the method returns as its result; but, because void methods return nothing, Java can reasonably include an implicit return; at the end of the body.

When you use a variable name in a method call, it _____ as the variable in the method header.

  It is important to note that although the values in the parameters (a and b) are exchanged by this code, the values stored in the arguments (x and y) ARE NOT EXCHANGED. The values stored in the arguments were copied to the parameters, but this transmission mechanism is ONE-WAY ONLY: FROM ARGUMENTS TO PARAMETERS. Thus, parameter transmission is asymmetrical. If an argument is a variable, the value stored in that variable always remains unchanged by a method call, even if we change the value stored in its matching parameter. The value in the box of the argument cannot be changed in a method call.

The situation gets a bit more complicated and interesting with references, because everything is more complicated and interesting with references. Recall how to copy a reference into a variable: make the variable refer to the same object (this describes how references are passed from arguments to parameters as well). Although the value in the box of the argument cannot be changed in a method call (it will still refer to the same object), the state of the object that it refers to CAN BE CHANGED in the body of the method by calling mutators/commands.

Let's look at the call frame for the multiRoll method to illustrate his behavior. Assume again that this method is defined in a class named Utility and that we declare DiceEnsemble dice = new DiceEnsemble(2,6); and call System.out.println(Utility.multiRoll(dice,3));

When you use a variable name in a method call, it _____ as the variable in the method header.
When you use a variable name in a method call, it _____ as the variable in the method header.

  Java passes the argument to the parameter by copying its reference, resulting in both the argument dice and the parameter d sharing the same object. Then, each time the multiRoll method calls d.roll(); the state of the shared object changes (see the rollCount and pips instance variables). The different values returned by getPipSum (7=2+5, 4=3+1, 5=1+4)account for the state changes shown for the local variable sum. So, the first statement prints the returned value from sum (16), and the second prints the value of rollCount from the object (now 3)

In summary, we cannot change arguments in a method call by changing the values stored in their matching parameters. But, if an argument and parameter share an object, then we can change the state of that object by calling a mutator/command method in the method. Once the method returns its result, the argument must refer to the same object, but THAT OBJECT'S STATE CAN BE CHANGED.

final parameters Finally, here is an update to the EBNF rule for parameter. It adds the option of specifying the keyword final before type.

    parameter <=>final] type identifier

If a parameter variable is declared final, we must treat it like any other final variable: we cannot change its state. So, throughout the method body it will always store the value to which it was initialized by its matching argument. It is frequently (but not always) the case that a method examines but does not store into its parameters. So, most of the time we can specify that a parameter is final. But, most Java style standards DO NOT require specifying parameters as final, even if they remain unchanged in the body of a method. I'm still deciding what I think is right in this case; meanwhile, you can choose either to include final in the code you write, to emphasize that the parameter does not change, or omit it; whatever you choose, be consistent.

Designing Methods When designing a method, first think of a descriptive name for it; then think about the other prototype information: what its return type is (if it is not void) and what parameters it needs (what are descriptive names for them and what are their types). Parameter variables are used to convey special information to the method; information that controls what a method computes. Methods may also have declare local variables, which are needed temporarily during the execution of a method; but these values do not have to be initialized by arguments outside the method. Finally, and this is typically the easiest part, write the statements that implement the method.

Most methods perform no input/output (unless that is the primary purpose of the method). Notice above that except for the promptInt methods, no others perform input or output. In some sense, methods get their "inputs" through their parameters; they supply their "output" either through a returned result or by changing the state of the objects that their parameters refer to. So, do not write methods that perform input/output unless that is their primary purpose.

EBNF for Defining Classes including Package and Imports Everything in Java is defined in a class: simple programs (as we will soon see), as well as library classes. The EBNF for a class relies heavily on the definition of full-member-definition (note package and class are keywords).

    package-declaration <=>package package-name;
    class-body                 <=>full-member-definition}

    class-definition         <= >package-statement]
                                           {import-declaration}
                                            access-modifiers class identifier {
                                              class-body
                                            }

The braces in the last rule stand for themselves (in the previous rules they stand for standard EBNF repetition). Most classes in Java are defined in their own .java file (although we can and will later use one file to define multiple classes).

Let's examine the three major parts of a class definintion. First, the package-statement. Every class is defined in one package, specified in the package-statement; if this option is omitted, the class is said to be defined in the anonymous package (the name of the anonymous packages has no characters in it). Whatever package this class is in, all other classes in that package are automatically imported for use in it. Second, if this class must refer to any classes in other packages, they must be imported explicitly in an import-declarations. Finally, the class itself is defined: it specifies its own access modifiers (almost always jut public) and includes any number of full-member-definitions.

Here is a trivial but complete class named Application. It is defined in the anonymous package, imports a neccessary class from the course library, and has a main method that performs some trivial I/O on the console.

import edu.cmu.cs.pattis.cs151xx.Prompt; public class Application { public static void main(String[] args) { int input = Prompt.forInt("Enter positive n"); System.out.println("You entered: " + n); } } Typically, such a class is stored in a file with the same first name as the class: Application.java. After discussing main methods, will see how to define complete classes for simple Java programs and libraries that define other methods.

The main Method Any Java class can define a special main method as one of its members; but, a method with this name is special only if it has exactly the following access modifiers and header (This method specifies an array of String as its parameter, although we will not use this parameter until we study how to use Java from a command line; we will see below how to tell the Eclipse IDE which special main method to execute.)

    public static void main(String[] args)

We can direct Java to start our program (a collection of one or more classes) automatically in any special main method. In fact, any project can include multiple classes, and each class can have its own special main method (this is actually quite useful, and we will discuss this feature when we discuss testing classes in more detail). In such a situation, we must tell Java WHICH special main method to start with.

In Eclipse, we specify the class whose main method is to be run by selecting the class either in the Package Explorer or in the Editor.

Methods in Applications We have seen how to declare one special static method in a class and have Java execute that method. Now we will learn how to define and call other static methods in a class. All we must do is place these other method definitions inside the class, along with the main method. Then, we can call these method from main or from each other.

Any static method in a class can call any other static method in that same class, just by using its name and supplying arguments that match its signature (or, if overloaded, one of its signatures). We can also be a bit more consistent (and verbose) and call a static method by prepending the class name to the method's name. The following Application class shows a simple example of such code.

import edu.cmu.cs.pattis.cs151xx.Prompt; public class Application { public static int factorial (int n) { int answer = 1; for (int i=2; i<=n;> Date Calculator #1

program. This program defines and used five static methods (and twelve static fields).
Definition Order Java uses a multi-pass compiler, which means that the methods and fields in a program can be defined in any order: Java first reads all the method headers and fields in the file, then in reads all the bodies, checking that they all use the types of these methods and fields correctly.

One standard way to write methods is in the "natural" order: if the body of method b calls method a, then method a is defined before method b. For example, we might have the following program form

method a's header {...no method calls...} method a's header {...call to a...} method c's header {...no method calls...} method d's header {...calls to b and c...} main methods' header {...calls to d and a...}

In fact, there may be many natural orders: e.g., in this example we could also meet the natural criteria by defining method c before method b or even before method a. The main method calls lots of other methods, so it typically appears last in the file.

In the "reverse natural" order: if the body of method a calls method a, then method a is defined after method b. In this case, the main method calls lots of other methods, so it typically appears first in the file.

main methods' header {...calls to d and a...} method d's header {...calls to b and c...} method c's header {...no method calls...} method b's header {...call to a...} method a's header {...no method calls...} In this way, the most powerful methods appear at the top; we can read the details of how they work aftward. Because Java uses a multi-pass compiler, these two orderings, or any others, are all legal. When we discuss mutually recursive methods, we will return to this topic again.

Now, some words on divide and conquer, and program complexity. Up until now, we have been putting all of our code in the main method, some of which have been a hundred or more lines of code. This practice is stopping here! From now on, we will be distributing complexity by writing methods, and placing them in the application program, or in class libraries. We can write, test, and debug each method (and each class) by idependently.

Each method, including main, should not comprise more than one or two dozen statements; when a method gets too complicated (it does "this" and "that") then write a "this" method and a "that" method, and have the original method call these two new methods to get its job done. Another rule for keeping the complexity of each method small it to prohibit more than one loop (the most complex Java statement to think about) per method -or allow multiple loops, but not nested loops.

Notice how the complexity has been distibuted in the date calculator program, in which each method, even main contains only a small number of statements.

Throwing Exceptions
(an introduction)
We have already discussed how to handle thrown exceptions with try-catch statements. Now is an appropriate time to begin discussing the other end of exception processing: how to throw them them after detecting a problem. The EBNF rule for throwing an exception (using the keyword throw) is trivial:

    throw-statement <=>throw expression;

where there is a syntax constraint that expression must refer to an object constructed from a class descended from the Throwable class. We will discuss class hierarchies later; for now we have seen the names of a variety of classes descended from Throwable: EOFException, NumberFormatException, and most important for our current needs, IllegalArgumentException, and IllegalStateException.

Exceptions are represented by classes; so, throwing an exception requires us to construct a new instance of the class, typically initializing its state by a String that describes the problem; this String can be further examined and printed when the exception is caught.

Given that our factorial method only works for non-negative integers, we might modify it as follows, to detect a bad argument and throw IllegalArgumentException with an appropriate message (rather than just returning 1). Notice how throws IllegalArgumentException now appears in factorial's signature.

public static int factorial (int n) throws IllegalArgumentException { if (n < 0) throw new IllegalArgumentException ("factorial: n ("+n+") must be non-negative"); int answer = 1; for (int i=2; i<=n;> A simple if statement, the first in the method, determines whether or not the argument is bad, and if so throws an exception. It is common to check all the necessary preconditions on arguments at the start of a method's body, grouping such code together and separating it from the code that actually performs the method's task (which executes only after all the preconditions on the parameters have been checked). In this example, if the argument matching parameter n is a negative value, Java constructs an instance of the IllegalArgumentException class (initialized with an appropriate error message), and throws that exception.

When a statement throws an exception, Java abandons sequential execution and tries to locate a catch clause to handle the exception, first inside the method in which it was thrown; if the method itself doesn't have one, Java goes back to the call site for the method (which is the body of some other method) and repeats this process there. If by repeating this process, Java eventually gets back to the special main method, and if there is no matching catch clause to handle the exception, Java prints the exception name, the exception's message (the String argument to the exceptions constructor), and a trace of all the methods that were called, leading up to the problem.

We will use throw statements as we continue to learn about writing constructors and methods in classes. We will come back to the topic of throw statements and try-catch statements, and exception classes at least once more (in the context of class hierarchies), to help us further understand this complex error detection and recovery mechanism. There we will learn how to write new exception classes and the difference between checked and unchecked exceptions.

Methods in Library Classes Although some static methods might be useful in just one application, many are general enough to be used in other (similar) applications. In Java, we can easily collect these methods into a class of related methods (all the source code in the same file), which we can easily import and use in other programs.

The Math class in the standard Java library serves exactly this purpose, as doe the Prompt class in the course library: each collects together a group of math-related or console i/o related methods. For example, we ccould easily group together all of the static methods and fields from the date calculator program into a DateUtility class as is shown below. Then, we could use such a class library in any program that must deal with dates. Examine the Date Calculator #2 program to see exactly how this mechanism works in a project.

public class DateUtility { //Returns whether year is a leap year? public static boolean isLeapYear (int year) {return (year%4 == 0 && year%100 != 0) || year%400 == 0;} //Returns the number of days in month (in year) public static int daysIn (int month, int year) throws IllegalArgumentException { if (year < 1) throw new IllegalArgumentException ("daysIn: year ("+year+") not positive"); if (month < JANUARY || month > DECEMBER) throw new IllegalArgumentException ("daysIn: month ("+month+") not in range [1,12]"); //Thirty days hath September, April, June and November... if (month == APRIL || month == JUNE || month == SEPTEMBER || month == NOVEMBER) return 30; //...all the rest have thirty one... else if (month == JANUARY || month == MARCH || month == MAY || month == JULY || month == AUGUST || month == OCTOBER || month == DECEMBER) return 31; //...except February (must be FEBRUARY in else: see possible exception) else /* if (month == FEBRUARY) */ return 28 + (isLeapYear(year) ? 1 : 0); } //Returns the ordinal (1st, 2nd, 3rd, etc) representing month, day, year public static int ordinalDate (int month, int day, int year) { int ordinal = 0; //Scan every earlier month, summing the # of days in that month... for (int m=JANUARY; m < month; m++) ordinal += daysIn(m, year); //...and add day in the current month return ordinal + day; } //Returns a date as an American or European String //e.g., for February 10, 1954 these return "2/10/1954" and "10/2/1954" public static String americanFormat (int month, int day, int year) {return month + "/" + day + "/" + year;} public static String europeanFormat (int month, int day, int year) {return day + "/" + month + "/" + year;} //Fields: all public static final (constants supplied by class) //These could be private, for use only in this class, // but what the heck, let programmers use them from this class // (with final, there is nothing a programmer can do to change them) public static final int JANUARY = 1; public static final int FEBRUARY = 2; public static final int MARCH = 3; public static final int APRIL = 4; public static final int MAY = 5; public static final int JUNE = 6; public static final int JULY = 7; public static final int AUGUST = 8; public static final int SEPTEMBER = 9; public static final int OCTOBER = 10; public static final int NOVEMBER = 11; public static final int DECEMBER = 12; }
  Recall that final variables (constants) in Java are written as upper-case identifiers. If their name consists of multiple words, separate them by underscores: e.g., MAX_CLASS_SIZE.

Given the use of a library class, the main method in the Application class must refer to its members by using both their class name and member name: e.g., int ordinal = DateUtility.ordinalDate(month, day, year);

Again, observe that inside this class, we refer to each member by just its name. Outside the class (in the Application class) we must refer to each static member by its class name followed by its member name.

Finally, note that there are no constructors for this class (and likewise no instance variables). We do not construct objects from this class; we just use the class name directly to refer to the methods that we want to call from this class.

Methods/Fields and the Eclipse IDE Methods are so common in programming, various parts of the Eclipse IDE have been built to deal with them easily. Here we will examine mechanisms in the Java and Debugger views that help us use methods in our programs.

The editor includes a mechanism to locate and display a method easily in a program or library class. When a class is active in the editor, the Outline window lists all the methods in the class. We can easily view a method in the editor by clicking its name in the Outline window. As the number of methods in a class grows, this mechanism becomes more and more useful for quickly navigating files.

To the left of each method header is small shaded circle, containing either a minus sign or a plus sign. The minus sign means the method is fully disclosed; the plus sign means the method body is non-disclosed/elided (we see only its header). Clicking the circle toggles between disclosed and elided method bodies.

We can also use the debugger to better understand methods and debug methods that we have written. The options displayed when we are stepping through a program appear as

When you use a variable name in a method call, it _____ as the variable in the method header.

  • Middle: The Step Over button (the arrow pointing over a bar, as we have discussed) executes a method as if it were a black box: it does not show what happens inside a stepped-over method, it just executes its entire body in one fell swoop.
  • Left: The Step Into button (the arrow pointing down between two bars) executes a method by first showing its parameters and local variables (in the Variables tab). Then, we can step through each statement in the method and watch how it executes. If we step through a return statement, we will be returned to the code that called the method. If the method we are stepping through calls another method, we can choose to step-into or step-over that other call.
  • Right: The Step Out button (the arrow pointing up out of two bars) executes all the remaining statements in the current method, up to and including its return statement.
Note, the single bar for the middle button represents an entire statement. Stepping over it means ignoring the details of any methods that are called in that statement. The double bars in the left and right buttons represent a block of code implementing a method. We can step into a method (start executing the first line of code in the methods) and step out of a method (finish executing the last line of code in the method).

When we step into a method, its parameter and local variables appear in the Variables tab. All its parameters will be intialized to the values of their matching arguments. The name of the method will also appear underneath Thread[main] at in the Debug tab. If it calls another method, that method's name will appear above it (now directly underneath Thread[main]); whenever a method returns, its name is removed from the Debug tab and control returns to the method that called it (the one right below it in the Debug tab).

If you click any method name in the Debug tab, it will show you the code that is executing in that method (in the editor window) and that method's parameters and local variables (in the Variables tab). In this way, it is easy to shift focus among the methods that are currently executing. The Application.main method remains at the bottom of these method names in the Debug tab, throughout the execution of the program.

In the example below, we are looking at the bottom of the daysIn method; note its parameters have been initialized: month is 2 and year is 2006. In fact, this method has already called the isLeapYear method (it is at the top of the methods, so it is the one currently executing), but we have refocused our attention back to the daysIn method that called it, by selecting this method in the Debug tab.

When you use a variable name in a method call, it _____ as the variable in the method header.

  After we select the isLeapYear method and continue single-stepping, we return to the ordinalDate method, which shows the position it is executing (in the body of the loop) and all its parameters and local variables listed in the order they were declared in: parameters month, day, and year; local variables ordinal and m -the loop index.
When you use a variable name in a method call, it _____ as the variable in the method header.

  Practice using these three kinds of stepping using the two Date Calculator programs. The time you spend becoming familiar with debugging features will pay for itself many times over during the semester: debugging is hard, and these tools help tremendously.
Defining Classes from which we Construct Objects We will now shift our focus from simple classes that have only static members towards more interesting and useful classes: those from which we can construct and manipulate objects/instances. We will first examine why/how these classes declare instance variables. Although instance variables are declared to be private, we wll learn that all other members in their class can manipulate them. Then we will learn how to write constructors that help initialize these instance variables. Finally, we will build on our knowledge of methods to learn how to write methods that manipulate instance variables. We will discuss multiple uses of the keyword this in the context of classes from which we construct objects

Classes in Java combine elements of both state and behavior. State is embodied in an object's private instance variables; behavior is embodied in the class's public constructors and methods, which manipulate these instance variables. Programmers think about classes from three important and different viewpoints: user, implementor, and designer.

  • When a programmer thinks about using a class, he/she is interested solely in its public members: what constructors can be used to to build objects and what methods can be called to perform useful operations on these objects. Such a programmer is interested in WHAT can be done, but not HOW it is done (so long as the implementation works and is efficient). Reading Javadoc is the prime way to learn this information.

  • When a programmer thinks about implementing a class, he/she is interested first in what public members the class will supply (again, what programmers using the class will be able to do); but in addition, he/she is also interested in HOW such members can be implemented. Typically, knowing WHAT requires reading Javadoc; knowing HOW requires writing Java code that specifies what state each object will store and how its method bodies work to manipulate this state. This programmer is often presented with many interesting decisions, because there are many ways implement the same functionality.

  • When a programmer thinks about designing a class, he/she is again interested solely in what public members the class supplies. This person must decide what members to include and then specify the semantics of each member so that (a) users understand WHAT to do with the class and (b) implementors understand HOW to implement it. Designers do this by writing the public prototypes in a class and documenting them with Javadoc.
These three views are a bit of a simplification, because often one person takes multiple roles, even all three: a programmer might need to use a a class for a specific application, so he/she designs a general class that will be usable for that application (and hopefully others), and then he/she impelments the class; and closing the circle, he/she uses it in the application. Good design is hard. A designer often needs lots of experience using/implementing classes before he/she can effective design them (so others can use/implement them easily).

In this course we will mostly take the roles of users (as we have in previous lectures) and implementors (as we will in this one). As implementors, we will typically be given a design, and then be required to implement it. To accomplish this process, we will have to indentify the state that each object stores, then declare it and define the required constructors and methods.

Finally, who tests classes? We will see that classes may be tested from all three prespectives.

  • The designer tests a class by developing a test suite along with the Javadoc; because the designer doesn't know anything about the implementation, this is black-box testing. Some test suites are open-ended (a driver) and some are closed (we will learn about JUnit testing).

  • The implementor tests a class by running the designer's tests against the implementation, fixing errors exposed by the testing. The implementor might also develop further tests based on the actual implementation used (this is white-box testing).

  • The user of a class implicitly tests it in an application program: if the application does not work as expected, it may indicate that the class(es) he/she is using are not correct (or, the user may just be using them incorrectly).
The situation of a non-working application is interesting. Whose fault is it: the user of a class (for using it incorrectly) or the writer of a class (for implementing it incorrectly) We will examine this perspective at the end of the lecture, when we summarize classes (focusing on private members).

The most important thing to know about a class is that any member defined in a class can refer to any other member defined in that same class, EVEN IF ITS ACCESS MODIFIER IS private. So, access modifiers restrict what members defined OUTSIDE a class can access; they do not restrict what members defined INSIDE a class can access. This rule allows a class implementor to declare instance variables private, so they cannot be directly accessed by code OUTSIDE the class, and still write constructors/method INSIDE the class that access them; in fact, often accessor/query methods just return the values stored in some private instance variable.

To illustrate all this material, we will closely examine two classes and their drivers: SimpleDiceEnsemble and Rational.

Instance Variables Let's start by looking at the implementation details for two sample classes. The SimpleDiceEnsemble class must store information characterizing the ensemble (number of dice and sides per die) and information about its current state (number of rolls, pip sum, whether all die show the same numer of pips). It declares its instance variables as follows. private int numberOfDice; private int sidesPerDie; private int rollCount; private int pipSum; private boolean allSame;

The Rational class is much simpler: it must store only the numerator and denominator of the rational number (fraction). It declares its instance variables as follows.

private int numerator; private int denominator;

Classes typically group the declarations of all their fields at the top or bottom (although there are no rules requiring this placement) Recall that Javadoc pages show fields first, so declaring them at the top is reasonable. Another perspective is that instance variables are private details, so declaring them at the bottom (out of the way) is reasonable.

Whenever new constructs an object, the first thing that it does is process all the field declarations in the class, which includes reserving space for all these field and initializing them. Unlike local variables, ALL FIELDS ARE INITIALIZED when they are declared: if we do not explicitly initialize them in their declarations, then Java implicitly initializes them: for the primitive types, it uses 0 for int, 0. for double, false for boolean, and the null character for char; for all reference types it uses null (meaning that they do not refer to any object).

In the examples above, all instance variables are initialized to 0 and false; in SimpleDiceEnsemble it is as if we had explicitly written

private int numberOfDice = 0; private int sidesPerDie = 0; private int rollCount = 0; private int pipSum = 0; private boolean allSame = false; We will soon see that constructors can (and often do) store more appropriate values in these variables, based on the arguments that we supply to the constructor. So technically, when a constructor stores a value into an instance variable, it is reinitialization, not initialization, because an initial value has already been stored there by Java, when it executes its declaration. Still, we will speak about initializing instance variables in constructors (and reinitialization if we want to be precise).

Constructors The main purpose of any constructor is to ensure that all the instance variables of the object being constructed are initialized correctly. This is done in the body of the constructor, which contains exactly the same statements that can appear inthe body of a void method.

For some instance variables a constructor may do nothing special: it leaves them with the initial values they received when declared. In other cases it initializes (actually reinitializes, given the discussion above) instance variables using the arguments passed to the constructor's parameters; the constructor often validates these arguments first (throwing IllegalArgumentException if they are incorrect).

There are classes, some quite complicated, in which constructors take no arguments and reinitialize no fields. In these cases, the fields are initialized correctly in their declarations (either explicitly or implicitly). The Timer class is one example of this kind of class. Its constructor looks like

public Timer () {} In fact, if we fail to define any constructor for a class, Java will automatically supply one that looks like this one (with the appropriate class name). But, if we define even one constructor for a class, Java will not overload the constructor(s) by defining this one.

Most classes define at least one constructor (and many overload the constructor). These constructors always have parameter that help reinitialize instance variables.

SimpleDiceEnsemble The first constructor defined in the SimpleDiceEnsemble class is public SimpleDiceEnsemble (int numberOfDice, int sidesPerDie) throws IllegalArgumentException { if (numberOfDice < 1) throw new IllegalArgumentException ("SimpleDiceEnsemble constructor: " + "Number of dice ("+numberOfDice+") < 1"); if (sidesPerDie < 1) throw new IllegalArgumentException ("SimpleDiceEnsemble constructor: " + "Sides per die ("+sidesPerDie+") < 1"); this.numberOfDice = numberOfDice; this.sidesPerDie = sidesPerDie; //rollCount: see declaration for implicit initializaton to 0 //pipCount and allSame indeterminate until roll } It first validates the values of its two parameters: if either does not make sense (we must have at least one die, and it must have at least one side), the constructor throws an IllegalArgumentException with an appropriate message. If the parameters do make sense, it copies them into two of the instance variables (reinitializing them). The other three instance variables are not reinitialized: the initial values they received when decared are correct: rollCount should always start at zero, and pipSum and allSame, although they store zero/false, really represent nothing, because the dice haven't been rolled yet (so any values would work for these).
Interlude: Variable Name Conflicts and Resolving them with "this" We must take a briefly diversion to discuss variable name conflicts and how to resolve them with the keyword this. There are three kinds of variable names in Java.
  1. The name of a parameter (defined in the constructor/method header)
  2. The name of a local variable (defined in the constructor/method body)
  3. The name of a field (defined in its class)
The Java compiler automatically implements a syntax constraint that prohibits defining a parameter with the same name as a local variable. So, the compiler would detect and report an error in following code public static int returnIt (int a) { int a = 1; return a; } In fact, Java points at the local variable declaration of a and says, "Variable 'a' is already defined in this method".

But, Java does allow instance variables to have the same names as parameters or local variables. When this happens, it is called a variable name conflict, because when we use that common name, there is a conflict as to what it means. Whenever there is a variable name conflict, the name by itself NEVER refers to the instance variable; it ALWAYS refers to the parameter or local variable. If instead we want to refer to the instance variable, we must preface its name with this. (this is a keyword). In a constructor, this is a reference to the object being constructed; and this.numberOfDice refers to the numberOfDice instance variable defined inside the class. In fact, writing this.numberOfDice is always a legal way to refer to the numberOfDice instance variable in the object being constructed, whether or not there is a variable name conflict.

So, in the constructor above, both parameter variables have a name conflict with two of the instance variables. The if statements, which check numberOfDice and sidesPerDie, are testing the parameter variables; the statements

this.numberOfDice = numberOfDice; this.sidesPerDie = sidesPerDie; store the values of the parameter variables (which disappear when the constructor finishes executing) into the instance variables (which exist so long as the object they are in exists). If we wrote numberOfDice = numberOfDice; then Java would just store the parameter's value back into the parameter variable: it stores nothing into the instance variable! Such a statement can cause a very hard to locate bug!

Another way around this whole "name conflict" problem is to change the parameter names; e.g. use number and sides. With no name conflicts, so we can write just numberOfDice = number; and sidesPerDie = sides. But, it is often the case that a well chosen name for an instance variable is replicated as a parameter name, because it captures exactly the right description; in such cases we must understand name conflicts and use this to resolve them.

To help avoid confusion, some style guidelines for Java specify that every access to an instance variable should be prefixed by this. to indicated explicitly it that is accessing a field. I'm still on the fence about this style rule.

Back to Discussing Constructors The second SimpleDiceEnsemble constructor has a much different form. First, it has no parameters; second, it does not throw any exceptions (this information is all specified in the constructor's header). We could have written this constructor as public SimpleDiceEnsemble () { numberOfDice = 2; sidesPerDie = 6; } which initializes the two instance variables so that the object represents two, six-sided dice. Note that because there are no parameter names in this constructor, so there are no name conflicts; therefore, we can use the instance variables directly with the this. prefix (although we could include this prefix for stylistic reasons).

But Java provides an even simpler way to define this constructor (even if it requires us to learn a new language feature: a different context in which to use this). The actual constructor appears as

public SimpleDiceEnsemble () {this(2,6);} In the constructor above this says "to initialize the instance variables, use another constructor from this class, one taking two int arguments. This is a common pattern, where one general constructor (with many parameters) is used by one or more special constructors (with fewer parameters) to do the initializations. Note that if we needed, we could add more statements to the constuctor AFTER this one (here, none are needed).

In fact, another way to handle all the initialization in this class is to declare

private int numberOfDice = 2; private int sidesPerDie = 6; private int rollCount; private int pipSum; private boolean allSame; The first constructor would work as before, reinitializing numberOfDice and sidesPerDie using the parameters. But the second constructor could be simplified to contain nothing in its body, because now when the instance variables are declared, they correctly represent two, six-sided dice.

Thus, constructors act as middlemen: they accept arguments, check these values for correctness, and ultimately use them to (re)initialize instance variables (if they are correct). Because instance variables are private, they can be initialized only in the declaration themselves, and reinitialized by a constructor defined inside the class.

Rational The first and most general constructor defined in the Rational class is public Rational (int numerator, int denominator) throws IllegalArgumentException { if (denominator == 0) throw new IllegalArgumentException ("Rational Construtor: - denominator 0"); if (numerator == 0) denominator = 1; //Ensure non-negative denominator; if a rational is // negative, its numerator is negative if (denominator < 0) { denominator = -denominator; numerator = -numerator; } //call gcd (greatest commmon divisor) // a private static method defined in this class int common = gcd(numerator,denominator); //or ...Rational.gcd(...) //name conflict this.numerator = numerator /common; this.denominator = denominator/common; } This constructor ultimately stores very special values into its two instance variables, carefully checking/altering its parameters before doing so. First, it cannot construct a rational value with a denominator or zero, is if the parameter has this values, it throws an exception. For all other numerators and denominators, it stores values according to the following rules.
  • Zero is always stored as 0/1
  • The denominator is always stored as a positive value
  • The numerator and denominator are reduced to have no common factors
So, if we declare Rational x = new Rational(2,-4); then x refers to an object that stores -1 for the numerator and 2 for the denominator (try some other examples). The parameters are examined and changed as needed in all but the last two statements; at the end, this. is used to resolve the name conflicts. Note the call to the method gcd, which is a static method defined in this class. Any non-static method can call a static method.

The following more special constructors create new objects by using this (in the sense of using another constructor in this class to initialize the instance variables)

public Rational (int numerator) {this(numerator, 1);} public Rational () {this(0, 1);}

In the first of these constructors, we specify a only a numerator parameter and by using this construct a rational with that value over 1; in the case of a parameterless constuctor, we construct a rational with the value 0 over 1; we could also have written this(0);

Blank Final Recall that we can declare blank final local variables. We can also declare blank final instance variables, but we must follow and additional constraint. Java allows us to declare an intance variable final and not initialize it in its declaration (the definition of blank final) But, we must initialize this variable in EVERY constructor that we write, otherwise the Java compiler will detect and report an error. Of course, the Java compiler will ensure that we never try to assign a second value to any final variable, including final instance variables.
Methods Method bodies follow the same rules as constructor bodies, in terms of their use of parameter variables, local variables, and instance variables (and in terms of this, variable name conflicts, etc). In fact, when we illustrate the call frame for a non-static method, it will show an implicit parameter named this and we will see how this parameter gets initialized by an implicit argument when such a method is called.

Recall that methods are divided into two categories

  • Mutator/command methods can access and store into instance variables declared in the class; they change the state of the object they are called on.

  • Accessor/query methods can access instance variables declared in the class, but not store into them; they do not change the state of the object they are called on.
We cannot tell just by looking at a method header whether it defines an accessor or a mutator (we must look at the method body or Javadoc). Yet, this is a fundamentally important piece of information about any method.

Often, one can tell which it is by the name of the method: accessor method names often begin with get. Also, void methods are almost always mutators: if they don't return a result, the only interesting thing they can do is change the state of the object they were called on. Some methods, like nextToken in the StringTokenizer clas act as both a mutator/command and accessor/query: changing an object's state and returning some value.

SimpleDiceEnsemble The SimpleDiceEnsemble class defines the roll method to be both a mutator/command and accessor/query (it is the only mutator in the class). It is defined as follows. public SimpleDiceEnsemble roll () { this.rollCount++; int firstThrow = this.randomDie(); this.pipSum = firstThrow; this.allSame = true; for (int i=2; i<=numberofdice;> Here, for clarity in the discussion to come, I have prefaced each instance variable by this. (even though there are no name conflicts). The roll method has no parameters; it declares two local variables (firstThrow and nextThrow) that it uses to change the rollCount, pipSum, and allSame instance variables

Methods often have few or no parameters, because they primarily operate on the instance variables of an object. The pips showing for each die are computed by the randomDie method, which We will examine later.

Let us see how to hand simulate a call to this method by using a call frame. Pay close attention to how this, the implicit parameter, is initialized by the implicit argument. Assume that we have declared

SimpleDiceEnsemble dice = new SimpleDiceEnsemble(2,6); and now we execute the statement dice.roll(); We illustrate the call of this method by the call frame below (assume that we roll a 3 on the first die and a 5 on the second).

When you use a variable name in a method call, it _____ as the variable in the method header.

  The implicit parameter this appears in every non-static call frame; roll declares no explicit parameters. this is always initialized to refer to the object on which the method was called. In this case, the call was dice.roll() so dice is the implcit argument and this is initialized to refer to the same object as dice (the equivalent of this = dice, which looks a lot like an argument initializing a parameter, even though both are implicit).

This method then examines and changes the instance variables in this object, as well as the local loop index variable i. Hand simulate this code, again assuming randomDie returns 3 when it is called the first time and 5 the second.

Note that by writing this.rollCount we are explicitly showing which object is being referred to when the rollCount index variable is accessed. As stated above, even if we wrote just rollCount, because there are no name conflicts, the meaning of using this variable is exactly the same as this.rollCount.

Notice too the call to this.randomDie(); it means to call the randomDie method on the object that this refers to, which is the same object on which roll is called. Generally, non-static methods inside a class can call other non-static methods in that same class, to help them accomplish their task on an object. As in the case of instance variables, writing randomDie() has exactly the same meaning here: calling another method on the same object that roll was called on. The randomDie method must be able to access the sidesPerDie instance variable to compute a random roll of a die with that many sides. In the actual code for SimpleDiceEnsemble, this is used only where necessary.

Finally, the return statement returns the reference stored in this: the code above does nothing with the returned result, but if we had instead written

System.out.Println(dice.roll().getPipSum()); Java would have called the getPipSum method on the returned reference, printing a value of 8.

The SimpleDiceEnsemble class defines many accessor methods, two of which are shown below.

public int getRollCount () {return rollCount;} public int getPipSum () throws IllegalStateException { if (rollCount == 0) throw new IllegalStateException("getPipSum - dice not rolled"); return pipSum; } Accessors are often simpler than mutators. The forms of many of these methods are actually quite common: just returning the value stored in one of the private instance variables. Note that by making the rollCount and pipSum instance variables private, no code external to the class can directly examine or change these variables, possibly trashing them; yet such code can always determine the current values stored in these instance variables indirectly, by calling their accessor/query methods. So, accessor/query methods allow any code to determine the value stored in a private instance variable without giving that code direct access to change that instance variable.

Note that the second method first checks that the pipSum instance variable actually stores a computed value before returning it; if the dice have not yet been rolled, it throws the IllegalStateException: the object is not in a good state yet to call this method.

Rational The Rational class is immutable. All its methods are accessors, although many construct and return values of primitive types or references to new Rational objects (the result of computing on the state(s) of old one(s), just as many String and BigInteger methods do). In the Rational class, I have adopted the style of always using this. when accessing instance variables. Two simple accessors that DO NOT construct objects are public int getNumerator() {return this.numerator;} public boolean equals (Rational other) {return this.numerator == other.numerator && this.denominator == other.denominator;} The first method just returns the value stored in the private numerator instance variable (but, we could write just return numerator;).

The second method returns whether or not (a) the object the method is called on, and (b) the object the method is passed as a parameter, are equal. Given the canonical way Rational stores these objects (zero as 0/1; denominators always positive; no common factors), they are equal if and only if both pairs of instance variables are equal. Note that if we did not store these objects canonically, then this method would not work: e.g., comparing the rational 1/2 vs 2/4; the rational 0/1 vs 0/12; the rational -1/2 vs 1/-2. Here, using this. adds a certain symmetry to our code (but, we could write just numerator == other.numerator and denominator = other.denominator).

Finally, note that there is NOTHING SPECIAL about the parameter name other (I've known students to get superstitious about this parameter name): so long as the parameter name appears identically in the code, we can use any name we want.

We illustrate this method call by the call frame below.

When you use a variable name in a method call, it _____ as the variable in the method header.

  Notice that the implicit parameter, this, refers to the object that a refers to: the implicit argument; the explicit parameter, other, refers to the object that the explicit argument b refers to. Again, there is nothing special about the parameter named other; we can name this parameter anything we want. If we called b.equals(a) the references stored in the implicit and explicit parameters would be swapped. This method call returns a result of false, because although the numerators are the same, the denominators are different.

Two more complicated accessors that DO construct objects are

public Rational abs() {return new Rational(Math.abs(this.numerator),this.denominator);} public Rational add (Rational other) { int a = this.numerator; // a c ad + cb int b = this.denominator; // --- + --- = --------- int c = other.numerator; // b d bd int d = other.denominator; // return new Rational(a*d + c*b, b*d); } The abs method constructs and returns a new Rational object, whose state is the absolute value of the state of the object that this method was called on; we know the denominator is always positive, so we can use its value directly. The return type of Rational means that this method returns a reference to an object that is an instance of the Rational class. In the abs method, we return a newly constructed Rational whose numerator is non-negative (all denominators are already positive).

The add method constructs and returns a new Rational object, whose state is the sum the states of the object that this method was called on and the object passed as the explicit argument. If we wrote

Rational x = new Rational(1,2), y = new Rational(1,3); Rational z = x.add(y); We would illustrate these variable and method call by the call frame below (note that for space reasons, I have left out the four local variables a, b, c, and d, which store the values 1, 2, 1, and 3 respectively).

When you use a variable name in a method call, it _____ as the variable in the method header.

  In this add method, we return a newly constructed Rational whose numerator and denomiator are computed according to the standard algorithm for adding rational values. Note that the code in the complicated constructor for this class will automatically reduce the results to lowest terms. If we call x.add(y) then this refers the state of the object that x refers to: the object on which add is called; and other refers to the state of the object that y refers to: the object that is an argument to add Of course, if we call y.add(x) then this and other would refer to the opposite objects (but since addition is symmetric, it would return the same result).

Because this method returns a reference to a Rational object, we can cascade our method calls. If we wanted to compute the sum of the objects all three variables refer to, we can write x.add(y).add(z) which first creates an object containing the sum of x and y, and then it adds this object to z, producing an object storing the total sum. We can also write x.add(y.add(z)), which produces the same result by adding objects in a different order.

Each of these classes include a toString method that returns a String catenating together all the state of the object (which is used mostly for debugging purposes). Such toString methods are often easy to write; examine them.

Special Methods There are two kinds of special methods that we examine here briefly: private and static. Both kinds occur in classes that we will write, but they do not occur frequently.
Private Methods First, sometimes a class will define private methods. Such a method is callable only from other methods defined in that class, not from any methods outside the class to use. Typically, private methods are small helper methods; they are useful for the implementor of the class, but not useful (or dangerous) for someone outside the class; like many methods, they hide some details. The SimpleDiceEnsemble defines the randomDie() method, which uses a random numuber generator to simulate throwing one die. The roll method has two calls to this one: one outside its loop and one inside the loop (which may get executed multiple times). private int randomDie () {return (int)Math.round(Math.random()*sidesPerDie + .5);} Notice that this method uses the instance variable sidesPerDie. The static method random defined in the Math class always returns a double result in the semiopen range [0,1); the expression transforms this value into an int between 1 and sidesPerDie, with each value equally likely to occur.
Static Methods Second, sometimes a class (one with a constructor) will define static methods, either public or private. The Rational class defines the prompt method as public static. public static Rational prompt(String s) { System.out.println(s); for (;;) try{ int numerator = Prompt.forInt(" Enter numerator "); int denominator = Prompt.forInt(" Enter denominator"); return new Rational(numerator,denominator); }catch (Exception e) {System.out.println("Illegal value entered; try again");} } Any class can call this method in its code as follows. Rational x = Rational.prompt("Enter x"); Recall that to use a static method outside a class, we must prefix its name by the name of its class NOT A REFRENCE TO AN OBJECT OF THAT CLASS. The console interaction would look like Enter x Enter numerator : 1 Enter denominator: 2

Why make this method static? Because its sole purpose it to construct/return a reference to an object. If we made this method non-static, we would have to write something like

//get an object (storing 0/1) to call prompt with Rational x = new Rational(); //store new value in x, throwing away 0/1 that we just created. x = x.prompt("Enter x"); In this case, we first construct an object to call the non-static method on, but we just throw away the original object, replacing it by a reference to an object containing the user-input rational. Thus, it is much simpler and easier to use this method if it is static.

The Rational class also defines the gcd method as private static.

private static int gcd (int x, int y) { ...lots of complicated code } This method is called only in the first constructor, to reduce to lowest terms the numerator and denominator (by dividing-out all common factors). Because this method is defined in the Rational class, we can call it as either gcd(numerator,denomiator) or as Rational.gcd(numerator,denomiator). Note that because this method is private, it cannot be called from anywhere but inside a constructor or method defined in this class.

Finally, notice that the randomDie method cannot be static. That is because it must refer to the instance variable sidesPerDie; static methods can refer only their parameter variables and local variables (see prompt and gcd). The fact that we can call static methods without objects means that they have no guaranteed access any object's instance variables. Of course, we could have rewritten it as a static method if we added a parameter:

private static int randomDie (int max) {return (int)Math.round(Math.random()*max + .5);} and then called this method in roll as randomDie(sidesPerDie), but I thought the former way was simpler.

Static Fields There are two main uses of static fields. The first and foremost is a place to declare constants (using the final access modifier) that other classes can use. For example, the DateUtility class declares final variables naming all the months. The Rational class declares the constants ZERO and ONE (both storing references to an object representing one of these values). Recall that one can call mutator on final variables to change their states, but one cannot store a new reference (to a different object) in a final variable. Because Rational is an immutable class (it contains no mutator methods) the instance values stored in these objects always will remain the same.

The second use of static fields is more subtle: we use them to store information shared by all objects in a class. Normally, each objects stores its own state in instance variables; but static variables are stored in a special spot that all objects can access.

Suppose that we wanted to be able to know how many times objects were constructed from a class (i.e., how many times new operated on a certain class). We can declare private static int allocated = 0; in the class, and then include the statement allocated++; in each constructor. Now, whenever an object is constructed, the static variable shared by all the objects in the class is incremented. Finally, we could define

public static int getAllocated () {return allocated;} to return its value.

So, what would happen if we did not declare this field to be static. If this information were stored in an instance variable (the only other choice), each object would store this value as part of its own state; each time an object was constructed it would initialize this instance variable to zero and then increment it in the constructor. Thus, if we constructed n objects, we would have n instance variables storing 1, not one static field storing n.

The final strangeness about static fields is that their declarations (and intializations) are done just once, the first time Java needs to do something with a class. Contrast this with instance variable declarations which are executed each time that new constructs an object.

Most fields in class with constructors are instance variables. The ones that aren't are mostly the constants described above. If you see other static fields, study them careful to understand them.

Writing Javadoc Comments Java is the first popular programming language to come with a special program (of course, written in Java) for documenting its classes. This is important, because most interesting programming involves locating a collection of useful classes and determining what constructors and methods they define, and how to use them (based on their syntax and semantics). Having all this information stored, indexed, and viewable via standard web browsers (with links), has made a big difference in my programming efficiency.

We have already studied how to read web pages produced by Javadoc (both for the standard Java library and classes that I have provided for this course). Now we will begin to learn how to write our own Javadoc comments, to document classes that we write ourselves.

We can run Javadoc on Java source code (.java files). Even if we have added none of the special comments desrcribed below, Javadoc still produces a skeletal web page listing all the fields, constructors, and methods in Summary and Detail tables. Such web pages, though, won't have any commentary, and none of the special parameter, return, and throws information.

In general, we can further document our classes with comments. Javadoc ignores general comments, but reads and process comments written in a special form: comments that start with /**. These are called Javadoc comments. Notice that a Javadoc comment is also a general comment (starting with /*) so it is also treated as whitespace by the Java compiler.

Here is the Javadoc commment prefacing the DiceEnsemble class. View it along with the Javadoc pages it generates in the Javadoc of Course API.

/** * Objects constructed from the <code>DiceEnsemble</code> * class act as collections of dice. * The number of dice in an ensemble (and the number of sides of * each die) can be controlled by the programmer. * The class models the basic operations need to roll the dice and * determine the number of pips showing -both for individual dice * and for the entire ensemble. * * @author Richard E. Pattis */ Javadoc copies the contents of this comment into the web page that it builds for this class; it appears near the top, right before the first Summary table. I write such comments in the .java file a special style, for ease of editing; each line is a sentence, with sentences longer than one line indented. The web browser renders this text as a nice paragraph.

Note that I said that Javadoc copies the contents of the message... and the web browser renders the text... This means that the comment can us embedded HTML markup tags; these tags are copied into the web page and rendered by the browser, just like normal HTML tags in text. Notice the use of <code>DiceEnsemble</code> to render the name of this class in the code font; in a multi-paragraph description, we use <p> to separate the paragraphs. Generally, use what HTML markup tags you are familiar with to format your documentation.

Finally, note the special Javadoc markup tag @author; Javdoc makes special use of these tag, often creating special HTML for them.

A typical constructor or method is documented by a Javadoc comment of the following form; the comment appear in the