Methods in Java Classes: Invocation

How is the method invocation related to its definition?

Overview

As we stated in the introduction, defining a method doesn’t actually cause it to be executed; instead, when we define a method, we are “teaching” the computer—more correctly, adding this method to the capabilities of the class in which the method is defined, or to the instances of that class. It is only when the method is invoked that it is executed.

However, before a method can be invoked at runtime, the definition of the method must be compiled, along with its invocations. When a method invocation is compiled, the Java compiler compares the invocation to the compiled method declaration, to make sure that the invocation will be valid at runtime. In order to write Java code effectively, we need to understand how this comparison is performed.

Syntax

The syntax of the method definition was already introduced in “Definition”. Now, let’s take a look at the invocation syntax:

[contextQualifier.]methodName([argument[, …]])

(Note that this does not show assignment of a method’s return value to a variable, or use of that return value in some other expression. At runtime, that assignment or other use takes place after the invoked method has completed processing; it is not actually part of the invocation syntax. However, when the value returned from a method invocation is used in a surrounding expression, that use will also be checked during compilation, for compatibility between the return type of the method and the type expected in the surrounding expression.)

Placeholders

contextQualifier

An instance (non-static) method must be invoked in the context of an object reference, whose reference type is the class (or interface) in which the method is declared, or a subclass (or subinterface) of that.

In an earlier example, we had this invocation of the convertC2F instance method, in the second line of a code fragment that also included creation of an instance of the Temperature class, followed by a declaration-with-assignment statement:

  Temperature t = new Temperature();
  double f = t.convertC2F(100);

Here, the context qualifier is the instance of Temperature referenced by the variable t.

A static method is invoked in the context of the class or interface (or a subclass or subinterface of that) in which the method is defined; thus, an appropriate value for this placeholder is a class name.

In the static version of the convertC2F example, we had this invocation of a static method, as part of a declaration-with-assignment statement:

  double f = Temperature.convertC2F(100);

Here, the context qualifier is the Temperature class itself.

If method A is being invoked from another method, B, and the context in which B was invoked is the same one in which A should be invoked, the context qualifier may be omitted. In practical terms, this means that when invoking a static method from a static or instance method in the same class, or when invoking an instance method from an instance method in the same class, we can usually leave the context qualifier out.

methodName

The name of the method to be invoked; this must match the declared method name exactly.

argument

An expression which will be evaluated prior to invocation, with the resulting value passed to the method being invoked. Any arguments must match the declared parameters of the method being invoked—that is, each argument’s type must be compatible with the type of the corresponding parameter, without skipping or reordering any of the arguments or parameters. (Java does not support optional parameters: every parameter in a method declaration must be matched by a corresponding argument in the invocation, or the invocation will not compile.)

If the method being invoked has no declared parameters, the invocation must similarly include no arguments—but the parentheses are still required.

Compilation

Method declaration

When a method definition—or just the declaration, for an abstract method—is compiled, the resulting bytecode contains the method signature (the combination of method name and parameter types, order, and number), along with the other elements of the method declaration (modifiers, return type, and throws clause, if any). Of course, the method implementation (if any) is compiled into the bytecode—but it is the declaration, not the implementation, that is used in when compiling any invocations of the method.

Method invocation

As noted above, an invocation of a method must match the declaration of an accessible method in the class specified by the invocation’s context qualifier. For example, if the invocation context is a class name, then the invocation must match a static method defined in that class, or defined in a superclass or implemented interface (or superinterface) of it. On the other hand, if the invocation context is a reference to an instance of a given class, then the invocation must match an instance or static method declared in that class (or in a superclass or implemented interface). If a match is not found, compilation of the invocation fails.

Example: compilation success

Here, we have a statement that successfully compiles to invoke the static method atan2, defined in the Math class.

double theta = Math.atan2(-1.0, 1.0);

Example: compilation failure

On the other hand, we have an invocation of the charAt method, defined in the String class, that doesn’t compile:.

char c = "bootcamp".charAt(5.0);

The problem shown above can be resolved by using a literal int value (or any expression that’s assignment-compatible to an int) as an argument to the charAt method. For example, the following invocation will compile (and execute) successfully:

char c = "bootcamp".charAt(5);