Concepts / Built-in Subroutines and Functions

Built-in Subroutines and Functions

A subroutine is a named set of program instructions designed to perform a task.

  • Programming

Why Repeated Work Needs a Name

Programs often need to do the same kind of job in several different places. Suppose a program must print the same divider line three times in one run. One approach is to copy the same lines of code three times. Another is to write those lines once and let the rest of the program use them whenever they are needed. The second option is the idea behind a subroutine.

What do you think happens?

If a program needs the same calculation or the same printed output in several places, would you rather keep its instructions in one place or in every place it is needed?

Reveal answer
Answer:

One place. A subroutine groups the instructions for a task, gives the group a name, and lets the program refer to that name wherever the task is needed.

Keeping one copy means a fix or change to the task happens once, not in every location. The rest of this article shows how the name and the call make this work.

What a Subroutine Is

Definition

A subroutine is a named set of program instructions designed to perform a task. It is a block of code that can be called multiple times from different parts of a program.

Two ideas are packed into this definition. The first is grouping: several instructions that together accomplish one task are kept as one unit. The second is naming: that unit has a name, so the program can refer to the whole task with a short label instead of listing every instruction again. A name stands in for a block of instructions, which is why one short line can replace many lines of code.

Key point

Writing a subroutine does not by itself make it perform its task. Grouping and naming the instructions only creates the subroutine. The task is performed when the program uses a subroutine call statement.

Calling a Subroutine Starts Its Work

A subroutine runs when the program calls it. The important word is called. A subroutine does not run just because it exists in the program. When the main program reaches a call statement, it requests that the named task be performed. Once the subroutine finishes its instructions, the main program continues with the line that follows the call. Because the same block can be called more than once, one piece of code can serve many moments in a single run.

Main programcalling lineSubroutinenamed task1. call statement2. return to the line after the call
When main calls a subroutine, which line runs next, and where does execution resume after the subroutine finishes?

Read the diagram as a sequence of messages. The main program stops at the call statement and hands control to the subroutine. The subroutine performs its instructions. Then control comes back to the main program at the line right after the call, and the main program resumes from there. The main program does not repeat the subroutine's instructions itself; it only asks for the task to be done.

java
Output
Start
----
Middle
----
End
----
Notes on the code
  • printDivider is the named group of instructions; its body contains the single print instruction
  • Each line printDivider(); is a call statement, which is the request for the task to be performed
  • The same subroutine is called three times, so the divider appears three times without its instructions being copied

Tracing One Subroutine Through a Run

Now follow the same program through its run, step by step. Notice that there is only one copy of the divider's instructions, but the subroutine is entered three separate times, once from each call statement in main.

main beginscall printDividerfirst callprintDivider bodyone copy of theinstructionsprint Middlenext line after first callcall printDividersecond callprint Endnext line after second callcall printDividerthird callmain endsprint Startenter subroutinereturn to first call sitecontinue mainenter subroutine againreturn to second call sitecontinue mainenter subroutine a third timereturn to third call site
In what order do the main program and the shared subroutine alternate during the run, and how many times is the subroutine entered?
Worked example

Tracing the shared divider through the run

Using the Greetings program above, list what the program prints and count how many times the printDivider instructions execute.

  1. 1
    Line 1 of main

    Start is printed by main itself. No subroutine is involved yet.

  2. 2
    First call

    The statement printDivider() is reached. Control moves to the subroutine, which prints ----. Control then returns to the line after the call.

  3. 3
    Middle line

    main prints Middle directly, then reaches the second call statement.

  4. 4
    Second call

    Control moves to the same subroutine, which prints ---- again, and returns to main.

  5. 5
    End line

    main prints End directly, then reaches the third call statement.

  6. 6
    Third call

    The same subroutine runs a third time and returns to main, which then finishes.

Result

The program prints Start, ----, Middle, ----, End, ----. The single subroutine is entered three times, and its instructions are written only once in the file.

What do you think happens?

If main calls printDivider() four times instead of three, how many lines of ---- are printed?

  • Three

  • Four

  • Five

Reveal answer
Answer:

Four

Each call statement requests one run of the subroutine, so each call prints one line of ----. The subroutine's instructions do not change; only the number of calls does.

Predefined Subroutines in Java

You do not always need to write every subroutine yourself. Java includes standard classes that contain predefined subroutines. These subroutines have already been written and can be used in a program. A program can therefore accomplish many tasks by calling existing subroutines instead of creating every group of instructions from the beginning.

Using a Subroutine as a Black Box

A subroutine can be treated as a black box. To use it, a programmer needs to know which subroutine to call and what task it provides. The programmer does not need to know its internal instructions or how those instructions were written. The call uses the subroutine as an available service while leaving its internal workings hidden.

Caller's inputinformation passed to thecallSubroutineinternal steps hiddenResult of the taskwhat the caller receivescalltask performed
What goes into a subroutine, what comes out, and which of its internal instructions can the caller ignore?

The diagram shows the caller's view. Something goes in through the call, the subroutine does its work, and a result comes out. The steps between those two points are the subroutine's internal instructions, and the caller can ignore them as long as it knows what the subroutine does. This is why a programmer can use a predefined subroutine without reading how it was written.

Subroutines in ThreeN2.java

The source describes ThreeN2.java, introduced in Section 4.4, as an improved version of the 3N+1 program. It is described as a program that uses subroutines and prints its output in neat columns. The source gives two reasons for this use. The first is code organization: separating work into named blocks makes the program easier to read and manage. The second is output formatting: the subroutines are part of how the neat columns are produced.

Mistakes Beginners Make with Subroutines

  • Common mistake

    Believing a subroutine runs just because it is written in the program

    Why it fails

    A subroutine performs its task only when the program reaches a call statement that requests it.

    Do this instead

    Write the call statement at each point where the task is needed.

  • Common mistake

    Copying the same instructions into several places instead of naming them once

    What it looks like

    Writing the divider's print line three times rather than calling one named subroutine three times

    Why it fails

    Repeated copies must all be changed whenever the task changes, and they make the program harder to read.

    Do this instead

    Group the instructions into one subroutine and call it wherever needed.

  • Common mistake

    Trying to read a subroutine's internal instructions before using it

    Why it fails

    A subroutine can be used as a black box, so the caller only needs to know what task it performs.

    Do this instead

    Confirm what the subroutine does and what it provides, then use the call.

  • Common mistake

    Assuming String methods can be called without a String object to act on

Practice Tracing Repeated Calls

EASY

Using the Greetings program from earlier, predict the output if main is changed so that the line printing Middle is followed by two calls to printDivider() in a row, and then the line printing End follows. Write out every line in order, then count how many times the subroutine is entered.

Hints
  • Follow the program from the top of main, executing one statement at a time.
  • Each call statement sends control to printDivider, and control returns to the line after the call.
  • Two calls in a row produce two divider lines before End is printed.

Key Takeaways

  • A subroutine is a named set of program instructions designed to perform a task, and it can be called multiple times from different parts of a program.
  • A subroutine runs only when a subroutine call statement requests it; after it finishes, control returns to the line after the call.
  • Java provides predefined subroutines in standard classes, and String objects contain subroutines for manipulating strings.
  • A subroutine can be used as a black box: a caller needs to know what it does and how to call it, but not its internal instructions.
  • ThreeN2.java uses subroutines to organize its code and to help format its output in neat columns.