Computing Concepts with Java Essentials
Laboratory Notebook
Chapter 7 - More about Methods

Your name:
Your email address:
Your student ID number:

Once this form has been customized for your institution, you can use this button to send your lab work. Be sure to read the instructions before starting your work.


Lab Objectives

To gain experience in


R1. Parameters

Consider the following methods:

   public static String replace(String s, String a, String b)
   public static double canVolume(double h, double r)

and these variables:

   String greeting = Hello!"
   int a = 10;
   int b = 4;

What is wrong with each of the following method calls ?


R2. Procedures that Modify Parameters

In Java, a method cannot modify contents of any variables that are passed into it. For example, consider this call to the procedure f:

Rectangle r = . . .;
int n = . . .;
. . .
f(r, n)

After the call, r still refers to the same Rectangle object as before the call, and n still contains the same number as before the call.

The procedure f can modify the state of the Rectangle object, for example, move it to another location. But it can't replace the object with a different one.

The procedure cannot modify the value of n at all.

  1. In Java, it is not possible to write a procedure triple in Java that achieves the following. Explain.
    int a = 4;
    triple(a);
    /* now a is 12 */

  2. Can you solve this problem by writing a method instead? How?
  3. Is it possible to write a procedure triple in Java that achieves the following? Explain.
    Rectangle r = new Rectangle(0, 0, 10, 20);
    triple(r);
    /* now r's width is 30 */

  4. Is it possible to write a procedure swap in Java that achieves the following? Explain.
    String a = "Adam";
    String b = "Bruce";
    swap(a, b);
    /* now a is Bruce, b is Adam */


P1. Return Values

In methods with more complicated branching of control, one way to insure a reasonable return value is to gather together all the possibilities and issue only one return statement from the very end of the block statement. Rewrite the pointsOfCompass method as follows:

  1. Introduce an additional variable string directionString
  2. Be more clever about the logic--first compute the major direction (north, east, south, west), then append an east or west if necessary
  3. Return the directionString from the end of the method only
public class Compass
{  /**
    * Construct a Compass
    * @param d the compass needle angle in degrees
    */
   public Compass(double d)
   {  degrees = d;
   }

   /**
    * Convert a numeric compass position to it's verbal equivalent
    * @param degrees the compass needle angle in degrees
    * @return the value as a compass direction ("N", "NE", ...)
    */
   public String pointsOfCompass()
   {  double octant = (degrees % 360) / 45.0 - 0.5;

      if (octant >= 7)
         return "North West";
      else if (octant >= 6)
         return "West";
      else if (octant >= 5)
         return "South West";
      else if (octant >= 4)
         return "South";
      else if (octant >= 3)
         return "South East";
      else if (octant >= 2)
         return "East";
      else if (octant >= 1)
         return "North East";
      else if (octant >= 0)
         return "North";
      else
         return "North West";
   }
   private double degrees;
}


P2. Eliminating Global Variables

Global (or static) variables may "work", but the advantages they offer are outweighed by the confusion they can cause. Since all methods can set a global variable, it is often difficult to find the guilty party if the global variable is set to the wrong value.

Consider this example.

public class Max
{  /**
    * Updates maximum if parameter is larger
    * @param  a the value to compare against maximum
    * @remark Uses static int maximum
    */

   public static void set_max(int a)
   {  if (maximum < a)
      {   maximum = a;
      }
   }

   public static int max3(int i, int j, int k)
   {  set_max(i);
      set_max(j);
      set_max(k);
      return maximum;
   }

   public static void main(String[] args)
   {  ConsoleReader console = new ConsoleReader(System.in);
      System.out.println("Please enter the first integer:");
       int i = console.readInt();
       System.out.println("Please enter the second integer:");
       int j = console.readInt();
       System.out.println("Please enter the third integer:");
       int k = console.readInt();
       int maximum = max3(i, j, k);

       System.out.println("The maximum is " + maximum);
   }

   public static int maximum;
}

Test this program. Does it work?

What would happen if your program computed the maximum of two data sets? Would it still work?

Re-write max3() to avoid the use of global variables, and to preserve the logic of the method.


R3. Variable scoping

Generally, we want to encourage you to define a variable when you first need it, but you have to pay attention to the scope. Find what's wrong with this method's variable scoping, then fix it.

/**
 * Select the maximum of three integer values
 * @param i an integer
 * @param j an integer
 * @param k an integer
 * @return the maximum of i, j, and k
 */
public static int maximum(int i, int j, int k)
{  if (i > j)
   {  int a;
      a = i;
   }
   else
   {   a = j;
   }

   if (k > a)
   {   return k;
   }
   else
   {   return a;
   }
}


R4. Method Names

Why are the following methods badly named? What names would be better?


R5. Method Comments

Sooner or later, you'll encounter cryptically named and uncommented work like the following.

public static bool cw(Rectangle r1, Rectangle r2)
{  return r1.getWidth() == r2.getWidth();
}

public static bool ch(Rectangle r1, Rectangle r2)
{  return r1.getHeight() == r2.getHeight();
}

public static bool c4dup(Rectangle r1, Rectangle r2)
{  return  cw(joe, mary) && ch(joe, mary);
}

public static void main(String[] args)
{  Rectangle r1;
   Rectangle r2;
   . . .
   if(c4dup(r1, r2))
      System.out.println("Same");
   else
      System.out.println("Different");
}

What do these methods do ?

Rewrite them with comments and more descriptive method and parameter names. Use:

/**
 * purpose
 * @param
 * @return
 */
 


P3. Asserting preconditions

Throw an IllegalArgumentException in the following example to signal that an improper input has occurred and to prevent the bad parameters from being utilized by the function.

public class PrecondExercise
{  /**
    * Compute seconds from midnight
    * @param hours hour of a clock time (between 0 and 23)
    * @param min minutes of a clock time (between 0 and 59)
    * @return the number of seconds between midnight and the clock time
    */
   public static int convertToSec(int hours, int min)
   {  /* your work here -- assert that hours and min are within input range */
      return hours * 3600 + min * 60;
   }

   /**
    * Compute the number of seconds between two clock times
    * @param hfrom the hours of the earlier time
    * @param mfrom the minutes of the earlier time
    * @param hto the hours of the later time
    * @param mto the minutes of the later time
    * @return the number of seconds between them
    */
   public static int secondsBetween(int hfrom, int mfrom, int hto, int mto)
   {  int secs = convertToSec(hto, mto) - convertToSec(hfrom, mfrom);
      /* your work here -- assert that the from time is before the to time */
      return secs;
   }

   public static void main(String[] args)
   {  ConsoleReader console = new ConsoleReader(System.in);
      System.out.println("Input start hours:");
      int startHr = console.readInt();
      System.out.println("Input start minutes:");
      int startMin = console.readInt();
      System.out.println("Input end hours:");
      int endHr = console.readInt();
      System.out.println("Input end minutes:");
      int endMin = console.readInt();
      System.out.println(secondsBetween(startHr, startMin, endHr, endMin)
         + " seconds elapsed");
   }
}

How does your program handle


P3. Recursion

Consider a method int digits(int) which finds the number of digits needed to represent an integer. For example, digits(125) is 3 because 125 has three digits (1, 2, and 5). The algorithm is defined as:

if n < 10, then digits(n) equals 1. Else, digits(n) equals digits(n / 10) + 1.

(Why? If n is less than 10, one digit is required. Otherwise, n requires one more digit than n/10.)

For example, if called as int num_digits = digits(1457), the following trace results:

digits(1457)
= digits(145) + 1
= digits(14) + 1 + 1
= digits(1) + 1 + 1 + 1
= 1 + 1 + 1 + 1

Do a trace of digits(32767)

Write int digits(int n) to be called by the following main():

public static void main(String[] args)
{  ConsoleReader console = new ConsoleReader(System.in);
   System.out.println("Please enter a number:");
   int testValue = console.readInt();

   int ndigits = digits(testValue);
   System.out.println("You need " + ndigits + " digits to represent " + testValue
      + " in decimal");
}

Don't forget to send your answers when you're finished.