slanted W3C logo

Day 08 — Method Invocation

In today's class we look at what happens a client invokes a method.

When You Invoke a Method: Part 1

When you invoke a method, the compiler needs to determine if the method exists, if the method has been invoked with the correct argument types, and which version of the method should be used.

The compiler uses 3 steps to determine if a method invocation is correct:

  1. determine the class to search for the method
  2. determine the method signature
  3. determine if the method is appropriate

Each step can be complicated. We only sketch what happens in the following slides.

Determine the Class to Search

The first step the compiler takes is to deduce the class that contains the method. The compiler does this by looking at the type of the class or object used to invoke the method:

import type.lib.*;

public class MethodExample1
{
   public static void main(String[] args)
   {
      Rectangle2.width = 8;
      Rectangle2.height = 3;
      int area2 = Rectangle2.getArea();
      
      Rectangle3 rect = new Rectangle3();
      rect.width = 5;
      rect.height = 5;
      int area3 = rect.getArea();
   }
}

In the example above, we have two methods named getArea.

The compiler deduces that the first method invocation belongs to the class named Rectangle2 (because the name Rectangle2 was used before the method name).

The compiler deduces that the second method invocation belongs to the class named Rectangle3 because the object rect used to invoke the method has the type Rectangle3.

Determine the Method Signature

The second step the compiler takes is to deduce which version of the method is being invoked. This is necessary because Java allows the implementer to use the same method name for different versions of the method. Methods in a class that share the same name are called overloaded methods. Consider the two methods named nextInt in java.util.Scanner:

int nextInt()
int nextInt(int radix)

In the example above, there are two methods named nextInt that have a different number of parameters.

Or consider the family of methods named min in java.lang.Math:

static double min(double a, double b)
static float min(float a, float b)
static int min(int a, int b)
static long min(long a, long b)

Here, all of the methods have the same number of parameters but the parameters have different types.

Determine the Method Signature

The compiler will search for all methods that are compatible with the method invocation. A compatible method is one that has the same number of parameters as the number of arguments supplied by the client, and the parameter types must match or be compatible with the types of the arguments supplied by the client.

Consider the two methods named nextInt in java.util.Scanner:

int nextInt()
int nextInt(int radix)

import java.io.InputStream;
import java.io.PrintStream;
import java.util.Scanner;

public class MethodExample2
{
   public static void main(String[] args)
   {
      InputStream in = System.in;
      PrintStream out = System.out;
      Scanner input = new Scanner(in);
      
      int first = input.nextInt();
      int second = input.nextInt(16);
      out.print("The first number is: ");
      out.println(first);
      out.print("The second number is: ");
      out.println(second);
   }
}

In the example above, the compiler determines which method to use based on the number of arguments supplied by the client.

Determine the Method Signature

Consider the family of methods named min in java.lang.Math:

static double min(double a, double b)
static float min(float a, float b)
static int min(int a, int b)
static long min(long a, long b)

public class MethodExample3
{
   public static void main(String[] args)
   {
      double min = Math.min(10.0, 20.0);
   }
}

In the above example, there is only compatible version of the method named min, namely min(double a, double b).

public class MethodExample4
{
   public static void main(String[] args)
   {
      int min = Math.min(10, 20);
   }
}

In the above example, all versions of the method named min are compatible based on their signature because the int arguments 10 and 20 can be promoted to long, float, or double.

Determine the Method Signature

When there are multiple compatible method signatures, the Java compiler will try to pick the most specific method.

Consider the family of methods named min in java.lang.Math:

static double min(double a, double b)
static float min(float a, float b)
static int min(int a, int b)
static long min(long a, long b)

public class MethodExample5
{
   public static void main(String[] args)
   {
      double minDouble = Math.min(10.0, 20.0);
      int minInt = Math.min(10, 20);
   }
}

Determine the Method Signature

static double min(double a, double b)
static float min(float a, float b)
static int min(int a, int b)
static long min(long a, long b)

Which version of min is selected by the compiler for each of the following statements?

Math.min( 1F, 2.0F );
Math.min( 1L, 2L );
Math.min( 1, 2L );
Math.min( 1F, 2.0 );

Determine if the Method is Appropriate

The final step the compiler performs is to determine if the most specific method is appropriate. One thing that the compiler checks is if a non-static method is called in a static way (which is illegal):

import java.io.InputStream;
import java.io.PrintStream;
import java.util.Scanner;

public class MethodExample6
{
   public static void main(String[] args)
   {
      InputStream in = System.in;
      PrintStream out = System.out;

      int first = Scanner.nextInt();
   }
}

In the example above, the expression in red is illegal because the method nextInt is not static and can only be called using an object.

When You Invoke a Method: Part 2

When you invoke a method, the compiler computes the values of each of the arguments from left to right. The compiler then passes the values (not the variables!) to the method.

Consider the following program:

public class MethodExample7
{
   public static void main(String[] args)
   {
      int x = 10;
      int y = 20;
      int z = Math.min(y, x);
   }
}

The method min receives the values 20 and 10; it knows nothing about the variables x and y.

When You Invoke a Method: Part 2

Java's mechanism for passing arguments to methods is called pass by value. What is the implication of method only receiving the value of the arguments?

Consider the following hypothetical method in the utility MakeBelieve:

static void swap(int a, int b)
Swaps the values of a and b.

Parameters:
a – a value
b – another value

public class MethodExample8
{
   public static void main(String[] args)
   {
      int x = 10;
      int y = 20;
      MakeBelieve.swap(x, y);
      System.out.print("x : ");
      System.out.println(x);
      System.out.print("y : ");
      System.out.println(y);
   }
}

What does the program print?

Self Check

  1. Key concepts 1—6 at the end of Chapter 3.
  2. Review questions 1—12 at the end of Chapter 3.
  3. Programming practice: exercises 3.12, 3.13, 3.18, 3.21

To Do For Next Lecture

  1. Read Section 3.2 in the textbook.