Subroutines and Parameters
A functional interface is a Java file that holds a specification for exactly one subroutine, and it is defined in a .java file just as a class is.
Why Programs Reuse Code
Suppose a program needs the same job done in three different places. One option is to copy the same lines of code three times. The other option is to write those lines once and let the rest of the program use them whenever they are needed. The second option is what a subroutine provides. A subroutine is a block of code that can be called multiple times from different parts of a program.
The important word in that definition is called. A subroutine does not run just because it exists in a program. It runs when the program reaches a point where it calls it. Because the same block can be called more than once, a single piece of code can serve many moments in one run of the program.
Before reading on, ask yourself this question: if a program needs the same calculation or the same printed output in several places, where would you rather keep the instructions for it, in one place or in every place it is needed? The main idea of subroutines is an answer to that question.
Predicting What a Specification File Contains
A functional interface is a Java file that holds a specification for exactly one subroutine. It is defined in a .java file just as a class is. Before looking at a real declaration, make a prediction. Think about how much of the file is about how the subroutine actually computes its answer, and how much is only about the shape of a call to it.
What do you think happens?
Does a functional interface file for valueAt contain the computation that valueAt performs?
Reveal answer
No, the file only records the specification: name, parameters, and return type
The source describes a functional interface as a specification. The declaration inside the braces is one line naming the subroutine, its parameters, and its return type. It states the shape of the subroutine, not how the subroutine computes its result.
Reading the valueAt Declaration
The source gives a first example as a whole functional interface squeezed onto one line. It is saved in a file named FunctionR2R.java, which matches the name of the interface, as with any Java class. The declaration has the following shape, read from left to right: the interface is named FunctionR2R, and inside the braces there is one line that names a subroutine called valueAt.
- interface FunctionR2R: the name of the functional interface, which also names the file
FunctionR2R.java - double before
valueAt: the return type, meaning the subroutine sends back a double valueAt: the name of the one subroutine this interface specifies- (double x): one parameter, of type double, whose parameter name is x
The specification records three facts about the subroutine: its name (valueAt), its parameters (how many and of what type, here one double), and its return type (here double). The source notes that a parameter name such as x is written in the declaration but is not really part of the specification. When you check a call against the specification, compare the number of parameters and their types, not the names.
What do you think happens?
Where in this file would computation for valueAt appear, if it were present?
Reveal answer
Inside the braces, where the body of the subroutine would be written
The source reasons that if the file contained computation, it would be found inside the braces. The braces here contain only the single declaration line, which is a specification with no computation in it.
Tracing Repeated Calls from main
Now consider how a main program uses that subroutine. The example below is an original illustration, not taken from the source. Suppose the main program calls valueAt three times at different points in its run. Each call pauses the main program, runs the subroutine, and then returns control to the line of main that made the call. Control moves back and forth between main and the subroutine in this order.
Notice that there is only one definition of valueAt, yet it is invoked three times. Each invocation starts from the same specification, and each one returns to the point in main where it was called. The main program continues its own statements after each return, so the three results can be used in different ways later in the run.
Finding Where a Call Disagrees with the Specification
Once you know the three facts, you can debug a broken use of a subroutine by asking where the use departs from the specification. Suppose some code calls valueAt with two numbers instead of one. The specification says there is one double parameter, so the mismatch is in the number of parameters. You do not need to guess. Compare the call against the declaration line by line.
A Second Declaration with No Return Value
The source gives a second example with a different shape. It describes a subroutine that does not return anything and takes two parameters, an array of strings and an int. The source does not supply a name for this subroutine in the excerpt, so the example here focuses on its shape rather than a specific identifier.
| Part of the specification | valueAt (first example) | Second example |
|---|---|---|
| Name | valueAt | Named in the declaration |
| Parameters | One double, called x | An array of strings and an int |
| Return type | double | void, meaning no value comes back |
Both declarations follow the same structure: a name, parameters, and a return type. Only the values filled in change.
A return type of void is still a return type. It tells the caller that no value comes back from the subroutine. The shape of the specification never changes; only the values placed into each part of it do.
How ThreeN2.java Uses Subroutines
The source points to ThreeN2.java as a concrete program that uses subroutines. It is introduced in Section 4.4 as an improved version of the 3N+1 program, and the source describes it as a program that uses subroutines and prints its output in neat columns. The source does not list the individual subroutines inside the file or show their code, so this article does not describe them in detail.
- Code organization: separating work into named blocks makes the program easier to read and manage.
- Output formatting: the program prints its results in neat columns, and the subroutines are part of how that formatting is achieved.
- When you open
ThreeN2.javayourself, look for the places where the program calls a named block of code, and compare them with the places where it prints results.
Mistakes Beginners Make with Subroutines
Common mistake Expecting a functional interface file to contain the computation
What it looks likeLooking inside the braces of FunctionR2R for the arithmetic that valueAt performs
Why it failsThe source describes the interface as a specification that records name, parameters, and return type for one subroutine
Do this insteadRead the file as a statement of what the subroutine looks like from the outside
Common mistake Matching a call by parameter name instead of by count and type
What it looks likeBelieving a call is wrong because the argument variable is not called x
Why it failsThe source notes that the parameter name is not really part of the specification
Do this insteadCompare how many parameters there are and what type each one has
Common mistake Assuming a subroutine runs just because it is written
Why it failsThe source stresses that a subroutine runs when the program calls it
Do this insteadFind the call site in the program to see when the subroutine actually executes
Common mistake Copying the same lines instead of calling one shared block when the same job is needed in several places
Practice Locating the Specification in a Call
A program calls valueAt with a single argument of type double at two different points. Using the declaration interface FunctionR2R { double valueAt(double x); }, identify the name, parameters, and return type that the specification requires. Then say whether each call matches the specification and explain your reasoning.
Hints
- The specification has three facts: name, parameters (count and type), and return type.
- Ignore the parameter name x when checking a call against the specification.
- Two calls that both pass one double to
valueAtmatch the parameter count and type.
Key Takeaways
- A subroutine is a block of code that can be called multiple times from different parts of a program, and it runs when the program calls it.
- A functional interface is a Java file holding a specification for exactly one subroutine, recording its name, its parameters (count and types), and its return type.
- The specification describes the shape of a subroutine from the outside; it does not contain the computation the subroutine performs.
- To debug a call, compare it against the specification fact by fact, starting with the parameter count and types, since parameter names are not part of the specification.
- Subroutines help organize code and format output, which is why
ThreeN2.javarelies on them.