What is the structure of a method definition?
The rules for defining a method in Java are very strict; in fact, they’re fairly strict in most programming languages, but Java is more strict than most. It takes some work to memorize the details—but as we begin to master them, we can begin to understand any Java methods we read, and start writing our own methods.
As noted in “Introduction: Terminology”, a method definition actually consists of two parts, the declaration and the implementation. Actually, this is the case for concrete methods, but not for abstract methods, indicated by the abstract
modifier on a method declared in a class. Abstract methods are discussed a bit more in “Modifiers”.
The syntax and example below identify the declaration and implementation parts of a method definition, and the elements of each.
Placeholders are indicated in italics, with optional elements in italicized square brackets.
[modifiers] returnType methodName([parameterType parameterName[, …]]) [throws exceptionType[, …]] {
[statements]
}
modifiers
Java methods may be declared with zero or more modifiers; these primarily determine the context and visibility of the method—that is, specifying whether the method will be executed in the context of the enclosing class as a whole, or in the context of individual instances of the class; and specifying whether (and to what extent) the method will be visible (and invokable) outside the enclosing class.
Though a comprehensive introduction to all of the possible modifiers is not within the scope of this module, the following are introduced in the “Modifiers” page that follows:
private
, protected
, public
static
abstract
returnType
The type of value that the method will return as a result of its execution, if any. This must match the declared name of that type exactly. For example, if a method is intended to return a value of the primitive type int
, then the return type must be written as int
, not Int
, INT
, etc. Similarly, if a method is intended to return a value of the class (object type) String
, then the return type must be written as String
, not string
.
If a method is not intended to return a value, void
is used—in place of a return type—to indicate this. Note that though we might say (a bit sloppily) that some method “has a void
return type”, void
isn’t actually a Java type itself, but indicates (only) that a method does not return a value.
methodName
The name of the method; this is nearly always written in lowerCamelCase
.
parameterType parameterName
The type of an input parameter value (spelled and cased exactly
according to the declared name of the type), along with the name by which that value is referenced in the method implementation. Both of these must be specified, for each parameter included in the definition.
As a rule, the name of a parameter is spelled in lowerCamelCase
.
Even if there are no parameters in the method definition, the enclosing parentheses must be included.
exceptionType
The type of exception that the method is capable of throwing. There may be zero or more of these; if there are none, then the throws
keyword must not be included in the method declaration. Any of these are specified by class name, so they will virtually always be written in UpperCamelCase
.
statements
The sequence of Java statements that must be executed in order to complete the higher-level operation that is the method’s purpose. If the method has a non-void
return type, this sequence must include at least one return returnValue;
statement, where returnValue
is an expression giving the value returned by the method.
Continuing with the temperature conversion example, we might define a method that performs the Celsius-to-Fahrenheit conversion as follows:
double convertC2F(double c) {
double f = 9 * c / 5 + 32;
return f;
}
There are a few things worth noting about this example:
As defined, this method has no modifiers; a couple that might be used here are public
and static
, which will both be introduced in “Modifiers”.
The return type and the type of the c
parameter are both double
. This is the Java primitive type that implements the IEEE double-precision floating-point format. double
can be used to represent real values in the interval $(-2^{1024}, 2^{1024})$, with up to 17 significant digits.
The name of the method, convertC2F
, doesn’t spell out the method’s purpose as explicitly as “convert Celsius to Fahrenheit”; however, in the context of temperature scales (presumably the key focus of the class in which the method is defined), where “C” and “F” are commonly used as abbreviations for the Celsius and Fahrenheit scales (respectively), this name would probably be sufficiently clear.
For the same reason that we used convertC2F
for the method name (that is, because the “C” and “F” abbreviations are widely used and understood in the context of temperature scales), the convertC2F
definition uses the simple parameter and variable names c
and f
, rather than the longer (but more self-documenting) celsius
and fahrenheit
.
(Notwithstanding the above, we often make our symbols—method names, parameter names, variable names, etc.—fairly descriptive, as a matter of practice; this is particularly the case when the symbol is long-lived, or visible over a broad scope.)
Local variable names, like parameter names, are written in lowerCamelCase
. Since both c
and f
are single-letter abbreviations for single-word names, they are following this rule, even though they don’t have any uppercase characters.
Apparently, this method isn’t capable of throwing any checked exceptions; thus, there is no throws
clause..
The method implementation (the body) consists of just two statements, enclosed between braces (which are required, even if the implementation contains no statements at all): one that declares the local variable f
and assigns it a value, computed with the formula given in the conceptual example (this is called a declaration-with-assignment statement); another that returns the value of the f
variable.
As mentioned previously, $\frac{9C}{5}$ can be equivalently expressed as $1.8C$; this indicates one possibility for simplifying the method implementation.
Another simplification would involve including the relevant computation in the expression following the return
keyword, and cut out the need to declare and assign the f
variable altogether.
These two simplifications can be combined:
double convertC2F(double c) {
return (1.8 * c + 32);
}
Note that the parentheses in the expression (1.8 * c + 32)
aren’t required; they’re used here to make it clear (e.g. to a reader who might not be very conversant with Java syntax) that it is the computed value of the expression that is returned by the convertC2F
method.
(In case you’re curious, the second form is more efficient at runtime—not because the 2 lines have been collapsed into 1, but because the combination of one floating-point multiplication and one floating-point division has been replaced by one floating-point multiplication.)