5.8.2. Defining Static Methods


Defining static methods

One of the most important features of Java, or of almost any programming language, is your ability to define new methods. You write a large piece of software by breaking it into a collection of small methods, each with a specific purpose.

The general form of a static method definition is

  static R name(arguments)
  {
    body
  }
where In the body, statement
  return E;
indicates that the method is finished and that its result is the value of expression E.

Here are some example methods.

  // Return the integer that is one larger than n.

  static int successor(int n)
  {
    return n+1;
  }


  // Return the larger of x and y.  (This is
  // equivalent to the Math.max method,
  // except that larger requires
  // its arguments to be of type double.
  // There are several different definitions
  // of Math.max.

  static double larger(double x, double y)
  {
    if(x > y)
    {
      return x;
    }
    else
    {
      return y;
    }
  }


  // Return the largest of x, y and z.

  static double largest(double x, double y, double z)
  {
    return larger(x, larger(y,z));
  }


  // Return true of n is prime and false if n is
  // not prime.
  //
  // Requirement: n > 1.

  static bool isPrime(long n)
  {
    //-------------------------------------------
    // We try potential factors up to the square
    // root of n, rounded to the nearest integer.
    //-------------------------------------------

    long s = (long)(sqrt(n) + 0.5);

    for(int k = 2; k <= s; k++)
    {
      if(n % k == 0)
      {
        return false;
      }
    }
    return true;
  }

Using your methods

As the definition of largest suggests, you should feel free to use the methods that you have defined as tools for defining other methods.

Use your defined method the same way you would a method from the library. For example,

  if(isPrime(2*y+1))
  {
    System.out.printf("%d is prime\n", 2*y+1);
  }
uses isPrime in a test. Notice that the form of the argument 2*y+1 is not required to match the name, n, used to refer to it in the definition of isPrime. Only the types must match. For any expression E of type long, isPrime(E) yields true if the value of expression E is prime. The argument name, n, in the definition of isPrime is just a convenient way to refer to the number that is passed within the body of isPrime.

When you use a method, you are said to call that method, and expression larger(7,4) is a method call expression.


Do not write types in method calls

After seeing a type in front of each argument in a method definition, some students try to write types in method calls too. Do not write types in method calls. For example,

  double z = largest(a, b, c);
makes sense. But
  double z = largest(double a, double b, double c);
does not make sense. You are not defining method largest here, so get rid of the types.

Similarly, do not write

  double z = static int largest(double a, double b, double c);
A method use is not a method definition.


Each call runs the method

Do not try to do anything special to get a method to run. A method call expression automatically runs the method. Sometimes inexperienced programmers are not sure how to get the result of a method, and write something like

  isPrime(x);
  if(isPrime(x)) 
  {
    ...
  }
believing that expression isPrime(x) in the if-statement refers to the answer produced by the statement just before it. But, since this program contains isPrime(x) twice, the method is called twice. The first statement calls isPrime(x) and just throws away its result. Get rid of it.


The mechanics of a method call

When a method is called, a new frame is created for it in the run-time stack. That frame holds all of the variables and parameters that the method uses. When the method returns, its frame is destroyed.

It is important to realize that a method's variables are associated with a frame, not with the method itself. When we look at recursion the distinction will become very important.


Exercises

  1. Define a static method sqr(x) that takes a real number x (type double) and returns the square of x (also of type double). For example, sqr(10.0) should return 100.0. Also write a contract for this method. Answer

  2. Without using the abs method, define static method absoluteValue(n) that takes an int n and returns its absolute value. Also write a contract for this method. Answer

  3. Define a static method isPerfect(n) that takes a positive integer n and yields true of n is perfect and false if not. Also write a contract for this method. See question 3 on the page on while-loops for a definition of a perfect number. Answer

  4. Using your isPerfect method from the preceding exercise, define a static method nextPerfect(n) that returns the smallest perfect number that is greater than n. Assume that n is a positive integer. For example, nextPerfect(1) = 6. Answer

  5. Suppose that method dbl is defined by

      static int dbl(int x)
      {
        return 2*x;
      }
    
    Is the following allowed in Java?
      int z = 10;
      int y = dbl(int z);
    
    Answer

  6. Is the following method definition allowed?

      static int dbl(int x)
        return x*x;
    
    Answer

  7. Rewrite the following two statements as one statement. Assume that method f has no side-effects and that variable q is not needed for anything else.

      int q = f(w);
      int r = f(q);
    
    Answer

  8. Suppose method g is defined as follows.

      static int g(int n)
      {
        if(n > 3) 
        {
          return 0;
        }
        else 
        {
          return 2*n+3;
        }
      }
    
    What is the value of expression g(3)? Answer

  9. Using static method g from the preceding problem, what is g(g(3))? Answer

  10. Write a Java definition of method seconds(ms), which takes an integer value ms representing some number of milliseconds (thousandths of a second) and returns a real number that is ms in seconds. For example, seconds(2001) = 2.001. Answer