Methods

All the programs we’ve written to date have been quite simple, well under fifty lines of code each. As programs grow in size it begins to make sense to break them into parts. Each part can perform a particular calculation and possibly return a value. This is especially useful when the calculation needs to be repeated at several different places in the program. It also helps to define a clearer picture of the flow of the program, much like an outline shows the flow of a book.

Each calculation part of a program is called a method. Methods are logically the same as C’s functions, Pascal’s procedures and functions, and Fortran’s functions and subroutines.

The above programs have already used a number of methods although these were all methods provided by the system. When we wrote System.out.println("Hello World!"); in the first program we were using the System.out.println() method. (To be more precise we were using the println() method of the out member of the System class, but we’ll talk more about that in Chapter 4.) The System.out.println() method actually requires quite a lot of code, but it is all stored for us in the System libraries. Thus rather than including that code every time we need to print, we just call the System.out.println() method.

You can write and call your own methods too. Let’s look at a simple example. Java has no built-in factorial method so we’ll write one. The following is a simple program that requests a number from the user and then calculates the factorial of that number.

We’ll use two methods in the program, one that checks to see if the user has in fact entered a valid positive integer, and another that calculates the factorial. However we’ll start by writing the main method of the program:

class Factorial {

  public static void main(String args[]) {

    int n;

    while ((n = getNextInteger()) >= 0)  {
      System.out.println(factorial(n));
    }

  } // main ends here

}

Among other things this code demonstrates that methods make it possible to design the flow of a program without getting bogged down in the details. We’ve simply named two methods, getNextInteger() and factorial() without worrying about their exact implementations. We can add the rest of the code in smaller, easier-to-understand pieces. Let’s write the factorial method first.

long factorial (long n) {

  int i;
  long result=1;

  for (i=1; i <= n; i++) {
   result *= i;
  }

  return result;

} // factorial ends here

We could have included this code in our main method, but the algorithm is much easier to understand by breaking the code into smaller, more manageable pieces. It’s also easier to test and debug. We can write a simple program that lets us test the factorial method before we worry ourselves with the much harder problem of accepting and validating user input. Here’s the test program:

class FactorialTest {

  public static void main(String args[]) {

    int n;
    int i;
    long result;

    for (i=1; i <=10; i++)  {
      result = factorial(i);
      System.out.println(result);
    }

  } // main ends here

  static long factorial (int n) {

  int i;
  long result=1;

  for (i=1; i <= n; i++) {
   result *= i;
  }

  return result;

} // factorial ends here

}

C++ programmers should take note that both methods are defined inside the class definition. Once again we see that in Java everything belongs to a class.

Let’s take a closer look at the syntax of a method:

 static long factorial (int n) {

  int i;
  long result=1;

  for (i=1; i <= n; i++) {
   result *= i;
  }

  return result;

}

Methods begin with a declaration. This can include three to five parts. First is an optional access specifier which can be public, private or protected. A public method can be called from pretty much anywhere. A private method can only be used within the class where it is defined. A protected method can be used anywhere within the package in which it is defined. Methods that aren’t specifically declared public or private are protected by default.

Next we decide whether the method is or is not static. Static methods have only one instance per class rather than one instance per object. All objects of the same class share a single copy of a static method. By default methods are not static.

Next we specify the return type. This is the value that will be sent back to the calling method when all calculations inside the method are finished. If the return type is int, for example, we can use the method anywhere we use a constant integer. If the return type is void then no value will be returned.

Next is the name of the method.

Then there are parentheses. Inside the parentheses we give names and types to the arguments of the method. A method may have no arguments or it may have one or several. These arguments can be used inside the method just like local variables.

Finally the rest of the method is enclosed in braces to make it a single block. The part inside braces is just like the main methods we’ve been exploring till now. There are variable declarations, some code, and finally something new, a return statement. The return statement sends a value back to the calling method. The type of this value must match the declared type of the method.

In general any line that looks like Text(arg1, arg2) or text(arg1) or text() is a method call. The compiler is responsible for distinguishing between parentheses that mean method calls and parentheses that serve as grouping operators in mathematical expressions like (3 + 7) * 2. The compiler does a very good job of this and you may safely assume that anything that isn’t clearly an arithmetical expression is a method call.

Methods break up a program into logically separate algorithms and calculations. In still larger programs it’s necessary to break up the data as well. The data can be separated into different classes and the methods attached to the classes they operate on. This is the heart of object oriented programming and the subject of Chapter 4 below.

Comments are closed.