Defining Static Subroutines
A subroutine must be defined somewhere, and the definition must supply its name, enough information to call it, and the code that runs on each call.
Why Write Instructions Only Once
Imagine a program that 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. A subroutine is the second option: a named block of code that can be called multiple times from different parts of a program.
What do you think happens?
If a program needs the same calculation in several places, where should the instructions for it live?
Reveal answer
In one place, and every part of the program uses that one copy
A subroutine is written once and then called from each point in the program that needs it. This is the central idea behind subroutines.
How Calling Works During a Run
The important word in the definition is called. A subroutine does not run just because it exists somewhere 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 a single run of the program.
The diagram below follows one main program that calls the same subroutine three times. Each call sends control into the subroutine, and each finished subroutine sends control back to the place where it was called. The subroutine itself is written only once.
Tracing three calls to one subroutine
A main program calls a subroutine named add three times, with the argument pairs (2, 3), (10, 20), and (7, 1). Trace where control goes and what comes back.
- 1Reach the first call
The main program reaches
add(2, 3). Control jumps into the add subroutine, and the two values are supplied to it. - 2Return from the first call
The subroutine finishes its statements and sends back 5. Control goes back to the point in the main program where the call was made.
- 3Reach the second call
Later the main program reaches
add(10, 20). The same subroutine runs again, from the same definition, and returns 30. - 4Reach the third call
The main program reaches
add(7, 1), which runs the same code again and returns 8.
Three calls and three returns, all using one definition of add. The code was written once and reused at three points in the run.
What a Complete Definition Must Provide
A subroutine must be defined somewhere in the program, and the definition has to carry three things. First, it names the subroutine. Second, it gives enough information that the subroutine can be called. Third, it contains the code that will run each time the subroutine is called. Every piece of the Java format exists to do one of these three jobs. Some pieces give the subroutine its identity, some tell a caller what it needs and what it gives back, and one piece holds the instructions that do the actual work.
A subroutine is a block of code that can be called multiple times from different parts of a program. A subroutine definition is the place where that block is written, and it must supply a name, enough information to call it, and the code that runs on each call.
The Java General Format
A subroutine definition in Java follows a fixed pattern. Each angle-bracketed word is a placeholder for the real content you would write in that position. Read the template from left to right, because the order is part of the format. Modifiers come first, then the return type, then the subroutine name. The name is followed by parentheses that enclose the parameter list. The statements go inside curly braces at the end. The parentheses and braces are written literally; only the words in angle brackets are replaced.
The template has five components, and each occupies one particular slot. Together they make up the whole definition. The modifiers and return type sit before the name, the name identifies the subroutine, the parameter list describes the information a caller supplies, and the statements are the code that runs on each call. The diagram below marks each slot in a concrete definition.
The name is the handle by which the subroutine is known. The parameter list is the part that describes the information a caller supplies when it calls the subroutine. The statements are the code that runs on each call. The return type and modifiers are the remaining two parts of the header that sit before the name.
Filling In the Template
The source does not supply this example. It is written only to show how the slots are filled. Suppose a programmer writes a subroutine that adds two integers and gives back the sum. The modifier is static, the return type is int, the name is add, the parameter list holds two int entries, and the statements compute and return the sum.
Notice that the parentheses are part of the fixed pattern. The parameter list here has two entries, but the template treats the list as one slot enclosed by the same parentheses that would enclose an empty list. Each slot keeps its place even when the content inside it changes.
Mistakes When Reading a Definition
Common mistake Assuming a subroutine runs just because it is defined
What it looks likeA program contains add but never reaches a line that calls it.
Why it failsA subroutine runs when the program calls it. Existing in the program is not the same as being called.
Do this insteadLook for the call sites. The code inside the definition runs only at the points where the program calls the subroutine.
Common mistake Reading the template in a different order
What it looks likePlacing the name before the return type, as in add int static(...).
Why it failsThe order is part of the format. Modifiers, return type, name, parameter list, and statements each have a fixed slot.
Do this insteadRead the header left to right: modifiers, return type, name, then the parenthesized parameter list, then the braced statements.
Common mistake Copying the same lines instead of writing one subroutine
What it looks likeRepeating the same addition code in three places in the main program.
Why it failsCopies must be maintained separately, and the purpose of a subroutine is to write the instructions once.
Do this insteadPut the shared instructions in one subroutine definition and call it from each place that needs it.
Common mistake When a call behaves unexpectedly, do not reread the whole program first. Ask which slot of the definition is responsible for the behavior.
Where ThreeN2.java Uses Subroutines
The source introduces ThreeN2.java in Section 4.4 as an improved version of the 3N+1 program. It describes the program as one 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.
The source gives two reasons ThreeN2.java relies on subroutines. The first is code organization: separating work into named blocks makes the program easier to read and manage. The second is output formatting: the program prints its results in neat columns, and subroutines are part of how that formatting is achieved. When you open the file, look for the places where the program calls a named block of code, and compare them with the places where it prints results.
Checking Your Reading of a Definition
A programmer writes the following subroutine: static int square(int n) { return n * n; }. Identify the modifier, the return type, the subroutine name, the parameter list, and the statements. Then say which slot of the definition you would check first if calls to square gave unexpected results.
Hints
- The modifier is the word that comes first, before the return type.
- The parameter list is the part inside the parentheses after the name.
- The statements are the code inside the curly braces, which runs on each call.
Key Takeaways
- A subroutine is a block of code that can be called multiple times from different parts of a program, so its instructions are written once and reused.
- A complete subroutine definition must supply a name, enough information to call it, and the code that runs on each call.
- The Java general format has five components in a fixed order: modifiers, return type, subroutine name, parameter list in parentheses, and statements in braces.
- Each time the main program calls a subroutine, control jumps into it and returns to the call site; the same definition serves every call.
ThreeN2.javauses subroutines for code organization and for formatting its output in neat columns.