Methods

Introduction to Methods

Frequently, we find it necessary to do the same thing several times in our code, but not necessarily sequentially, like we saw in examining looping structures. For example, we might need to print an account balance to the screen at several different points in our program, or we might need to apply the same formula to several different variables throughout our code, or we might need to initialize and then later re-initialize some variables etc...

A method in Java is a construct that allows the same task to be performed repeatedly anywhere throughout your code, while only defining and implementing that task once. Methods can also serve as mathematical functions, in that the task they perform can produce some output value.

As we will see, the particular way methods are defined and used has an additional benefit: we are able to "hide" their implementations -- which goes a long way to reducing complexity in our code.

Methods are defined separately from one another, but are called upon to do their task from within some other method (including, but not limited to, the "main" method, which governs the overall flow of your program).

When a method is called upon to do its thing, we say that we are invoking the method.

Methods may need to have some sort of input to complete their task. For example, if a method is required to print out an account balance, it might need to know the account number in question. If a method is to print out the maximum of two numbers, then it will need to know what the two numbers are. These inputs are called parameters.

Some methods simply do some task. Other methods might need to return some sort of output of a given type. Still others will do both of these things.

Both the (input) parameters and the return type (of the output) are specified in the first line of a method's definition, called the method header, while the code that specifies what the method actually does is called the method body.

Defining a Method

Consider the following example of a method definition:

public static int max(int num1, int num2) {   // <-- method header
   int result;                                // <--- start of method body

   if (num1 > num2)
      result = num1;
   else
      result = num2;

   return result;                             // <--- end of method body
}

In the example method defined above:

The return Statement

Notice that the method body contains a collection of statements detailing exactly what the method is to do. If the method is to produce some output, a return statement is required.

Syntax for a return statement

return outputValue;

Calling a Method From Another Method

The method defined above could then be called from the main method (or any other method allowed to use it) in a manner similar to the following:

public static void main(String[] args) {
   int i = 3;
   int j = 4;
   int m;

   m = max(i,j);

   System.out.println("The max is " + m);   \\prints "The max is 4"
}

Here's another example of a method defined (in red) that computes and returns the distance of a point (x,y) to the origin in the Cartesian plane, and the call made to the method inside of main() (shown in blue)

public class Main {

   public static double distanceToOrigin(double x, double y) {
    return Math.sqrt(x*x + y*y);
   }

   public static void main(String[] args) {
    double x = 5.0;
    double y = 12.0;
    
    double d = distanceToOrigin(x,y);
    
    System.out.println("d = " + d);             //prints "d = 13.0"
   }
}

Method Signatures and Overloading

The combination of the method name and the parameter list is called the method signature. One can actually define several different methods with the same name, as long as they have different method signatures (i.e., they are expecting different types/orders of input). This is a useful practice called overloading a method. For example, suppose you wanted to find the maximum of two given doubles instead of two given ints. Overloading allows one to use the method name "max" for both tasks. Java figures out which method is actually being called by examining the input parameters passed and determining which method signature matches those parameters.

Example of Overloading

public static int max(int num1, int num2) {
  if (num1 > num2)
     return num1;
  else
     return num2;
}

public static double max(double num1, double num2) {
  if (num1 > num2)
     return num1;
  else
     return num2;
}

System.out.println(max(1,3));     //prints "3"
System.out.println(max(1.0,3.0);  //prints "3.0"
System.out.println(max(1.0, 3);   //prints "3.0"  
                                    //(Note: 3 is promoted to a double)

Call Stacks

Value-Returning Methods

Example

public static int sign(int x) {
  if (x < 0) {
     return -1;     //error -- what gets returned if x >= 0?
  }
}

Calling Methods Defined in Other Classes

To invoke a static method of a class (i.e., a method that is not tied to a specific object, but to an entire class), use the following syntax:

ClassName.methodName(list of parameters);

Here is a specific example...

int number = (int) (Math.random()*100);

Pass-by-Value

When invoking a method, remember -- the value of the argument is passed to the method parameter. The variable itself is not affected (i.e., a new stack is created for the method called). This is referred to as pass-by-value.

Consider the following example:

public static void main(String[] args) {
  int i = 2;
  myMethod(i);                            //prints "3"
  System.out.println(i);                  //prints "2"
}

public static void myMethod(int num) {
  num = num + 1;
  System.out.println(num);                
}

Advantages of Methods

Scope of Local Variables