Java Parameters

These are some notes that I'm working on to explain how parameters work for Java methods. The notes aren't finished, and they are really aimed at data structures students, but you should benefit too. --Michael

 

 

 

E very programmer requires an unshakable understanding of methods and their parameters. This section illustrates these issues and other issues that arise in Java, such as how to test whether two objects are equal to each other and how to make a copy of an object. The examples use a new class called Location , which will be placed in a package called edu.colorado.geometry .

The purpose of a Location object is to store the coordinates of a single point on a plane, as in the picture shown here.

The location p in the picture lies at coordinates x = -1.0 and y = 0.8. For future reference, you should know that Java has similar class called Point in the java.awt package. But Java’s Point class is limited to integer coordinates and used primarily to describe points on a computer’s screen. I thought about using the same name Point for the example class of this section, but I decided against it because a program might want to use both classes. It’s not legal to import two different classes with the same names (though you can use a full type name such as java.awt.Point without an import statement). The Location Class

The diagram to the right shows several sample locations. We'll uses these sample locations to describe the Location constructor and methods listed here:

The Location class is small, yet it forms the basis for an actual data type that is used in drawing programs and other graphics applications. All the methods and the constructor, are listed in the specification of the Location class. The specification also shows one way to implement the class. After you've looked through the specification, we'll discuss that implementation.

Static Methods

The implementation of the Location class has several features that may be new to you. Some of the features are in a method called distance, with this specification:

 o distance
public static double distance(Location p1,
                             Location p2)
Compute the distance between two Locations.

Parameters:
p1 - the first Location
p2 - the second Location
Returns:
the distance between p1 and p2
Note:
The answer is Double.POSITIVE_INFINITY if the distance calculation overflows. The answer is Double.NaN if either Location is null.
For example, consider the locations p and s in Figure 3. Along a straight line, the distance between these two locations is about 3.36. Using the distance method, we can create these two locations and print the distance between them as follows:

   Location p = new Location(-1, 0.8);
   Location s = new Location(1.7,-1.2);
    
   double d = Location.distance(p, s);
   System.out.println(d);
This code prints the distance between the two locations--a little bit more than 3.36.

The distance method is modified by an extra keyword: static . The static keyword means that the method is not activated by any one object. In other words, we do not write p.distance or s.distance . Instead we write Location.distance .

Because the distance method is not activated by any one object, the method does not have direct access to the instance variables of the a location that activates the method. Within the distance implementation, we cannot write simply x or y (the instance variables). Instead, the implementation must carry out its compu-tation based on the arguments that it's given. For example, if we activate Location.distance(p, s) , then the distance method works with its two arguments p and s. These two arguments are both Location objects. We need to know exactly what happens when an argument is an object rather than a primitive value such as an integer.

Parameters That are Objects

What happens when Location.distance(p, s) is activated? For example, suppose we have the two declarations shown on the previous page for p and s . After these declarations, we have these two separate locations:

Now we can activate the method Location.distance(p, s), which has an implementation that starts like this:

   public static distance(Location p1, Location p2)
   {
      ...
The names used within the method ( p1 and p2 ) are usually called parameters to distinguish them from the values that are passsed in ( p and s ). On the other hand, the values that are passed in ( p and s ) are called the arguments. Anyway, the first step of any method activation is to use the arguments to provide initial values for the parameters. Here's the important fact you need to know about objects:

When a parameter is an object, such as a Location, then the parameter is initialized so that it refers to the same object that the actual argument refers to.

In our example, Location.distance(p, s), the parameters p1 and p2 are initialized to refer to the two locations that we created, like this:

Within the body of the distance method we can access p1 and p2 . For example, we can access p1.x to obtain the x coordinate of the first parameter. This kind of access is okay in a static method. The only forbidden expression is a direct x or y (without a qualifier such as p1 ).

Some care is needed in accessing a parameter which is an object. For instance, any change to p1.x will affect the actual argument p.x . We don't want the distance method to make changes to its arguments; it should just compute the distance between the two locations and return the answer. This computation occurs in the implementation of distance shown here:
   public static double distance(Location p1, Location p2)
   {
      double a, b, c_squared;

      // Check whether one of the locations is null.
      if ((p1 == null)  ||  (p2 == null))
         return Double.NaN;
               
      // Calculate differences in x and y coordinates.
      a = p1.x - p2.x;
      b = p1.y - p2.y;
      
      // Use Pythagorean Theorem to calculate the square of the distance.
      // between the locations.
      c_squared = a*a + b*b;
      
      return Math.sqrt(c_squared);
   } 

The implementation also handles a couple of special cases. One special case is when an argument is null. In this case, the corresponding parameter will be initialized as null, and the distance method executes this code:

      // Check whether one of the locations is null.
      if ((p1 == null)  ||  (p2 == null))
         return Double.NaN;

If either parameter is null, then the method returns a Java constant named Double.NaN . This is a constant that a program uses to indicate that a double value is "not a number."

A second special case for the distance method is the possibility of a numerical overflow. The numbers obtained during a computation may go above the largest double number or below the smallest double number. These numbers are pretty large, but the possibility of overflow still exists. When an arithmetic expression with double numbers goes beyond the legal range, Java assigns a special constant to the answer. The constant is named Double.POSITIVE_INFINITY if it is too large (above about 1.7308), and it is named Double.NEGATIVE_INFINITY if it is too small (below about - 1.7308). Of course, these constants are not really "infinity." They are merely indications to the programmer that a computation has overflowed. In the distance method, we indicate the possibility of overflow with this comment in the specification of the method.

The Return Value of a Method May be an Object

The return value of a method may also be an object, such as a Location object. For example, the Location class has this static method that creates and returns a new location that is halfway between two other locations:

 o midpoint
public static Location midpoint(Location p1,
                               Location p2)
Generate and return a Location halfway between two others.

Parameters:
p1 - the first Location
p2 - the second Location
Returns:
a Location that is halfway between p1 and p2.
Note:
The answer is null if either p1 or p2 is null.
   public static Location midpoint(Location p1, Location p2)
   {
      double xMid, yMid;
      
      //Check whether one of the locations is null.
      if ((p1 == null)  ||  (p2 == null))
         return null;
      
      // Compute the x and y midpoints.
      xMid = (p1.x/2) + (p2.x/2);
      yMid = (p1.y/2) + (p2.y/2);
      
      // Create a new location and return it.
      Location answer = new Location(xMid, yMid);       
      return answer;
   }
The method creates a new location using the local variable answer , and then returns this location. Often the return value is stored in a local variable such as answer , but not always. For example, we could have eliminated answer by combining the last two statements in our implementation to a single statement:

   return new Location(xMid, yMid);
Either way--with or without the local variable--is fine.

Here's an example to show how the static midpoint method is used. The method creates two locations and then computes their midpoint:

   Location low = new Location(0, 0);
   Location high = new Location(1000, 5280);
   Location medium = Location.midpoint(low, high);

In this example, the answer from the midpoint method is stored in a variable called medium . After the three statements, we have three locations, drawn here:

The complete Location implementation is available in the file Location.java.