Concepts / Static Subroutines and Variables in Java

Static Subroutines and Variables in Java

Modifiers appear at the front of a subroutine definition and set characteristics such as whether it is static or public.

  • Programming

Why Programmers Read the Header First

A subroutine is a block of code that can be called multiple times from different parts of a program. Before you use one, you need to know what it promises and what it needs. Experienced programmers rarely read the body of a subroutine first. They read the header, the line that comes before the braces and the code inside them. The header describes how the subroutine can be used: what it is, what it hands back, and what it needs to be given. You can think of the header as a short contract between the subroutine and anyone who calls it.

What do you think happens?

If a subroutine's header uses the word void in the return type position, what does it hand back to the code that calls it?

Reveal answer
Answer:

No value. The word void means the return value is empty or non-existent, so callers should not expect any result from it.

The source explains that void marks a subroutine that is not a function. Such a subroutine does its work, but it does not give a value back to the caller.

Reading a Header from Left to Right

Read a header from left to right and you meet three kinds of information in order. First come the modifiers at the front, words such as static or public that set characteristics of the subroutine. Next comes the return type, which describes what kind of value the subroutine gives back, or the word void when it gives back nothing. After the return type comes the subroutine's name. The parameter list sits last, inside the parentheses that follow the name. For each piece, ask the same question: what does this part promise or require when someone uses the subroutine?

publicmodifier: accessstaticmodifier: class-levelvoidreturn type: no valueprintTablename(int n)parameter list: type thenname
In a line like public static void printTable(int n), which part tells me what the subroutine returns, what it is called, and what it needs before I read its body?

The diagram labels each piece of one header. Reading it once, you learn that the subroutine is public and static, that it hands nothing back because of void, that it is called printTable, and that it needs one int value, which it will refer to as n inside its body. You learned all of that without reading a single line of the body.

What Modifiers Set

Modifiers are the words that can appear at the start of a subroutine definition, before the return type. Their job is to set characteristics of the subroutine. The source names static and public as the two modifiers it has encountered so far, and it highlights whether a subroutine is static as one such characteristic. Modifiers change how a subroutine behaves or is accessed. They do not change what the subroutine computes.

A helpful way to hold this idea is to treat each modifier as an answer to a yes-or-no or which-kind question. One question is whether the subroutine belongs to the class as a whole rather than to one object. Another is whether it is open for outside code to call. Notice what modifiers do not answer. They do not describe the values the subroutine accepts or returns. Those jobs belong to the return type and the parameter list.

Return Type: Function or void

The return type sits between the modifiers and the subroutine's name, and it depends on what kind of subroutine you are writing. A function is a subroutine whose job is to compute some value. For a function, the return type names the type of value that comes back to the caller. That type can be a type name such as String or int, or an array type such as double[]. If the subroutine is not a function, it does not hand a value back. In that case the return type position holds the special word void, which indicates that the return value is empty or non-existent.

FeatureFunctionSubroutine with void
JobComputes some valueDoes work without handing a value back
Return type in headerA type name such as int, String, or double[]The word void
What the caller can expectA value of the declared typeNo result
Example headerpublic static int square(int n)public static void printTable(int n)

Comparing a function with a subroutine whose return type is void

The word void carries a promise of its own. When a header says void, callers should not expect any result from that subroutine. When a header names a type, callers should expect a value of that type to come back. Reading the return type therefore tells you immediately whether the subroutine can be used inside an expression that needs a value.

Parameter Lists as Inputs

The parameter list sits inside the parentheses that follow the subroutine's name. Parameters carry information from outside the subroutine into it, so that its internal computations have something to work with. The source calls parameters part of the interface of a subroutine, meaning they are the part callers must match when they use it. A parameter declaration has the form type followed by parameter name, and the parameter list can be empty.

Consider a television with a method that changes the channel. The method needs to know which channel to switch to, so it needs an input. If a channel number is an integer, the parameter's type is int. The parameter is the spot in the header where the subroutine says what kind of input it expects and gives that input a name it can use inside its body.

Tracing Repeated Calls from Main

A subroutine runs when the program calls it, not merely because it exists in the file. The important word is called. Because the same block can be called more than once, one piece of code can serve many moments in a single run. In the Printer program above, main calls printTable three times. Each call transfers control into printTable, the body runs with n set to the value passed in, and then control returns to main so that main can continue with its next line.

mainfirst statementprintTable(3)prints n = 3mainresumes after call 1printTable(5)prints n = 5mainresumes after call 2printTable(7)prints n = 7mainresumes after call 3call 1returncall 2returncall 3return
When main reaches a call to a subroutine, where does execution go, and where does it resume after the subroutine finishes, each time it is called?

Read the diagram from top to bottom to trace one run. Main starts, then reaches its first call, and control moves into printTable with n equal to 3. When the body finishes, control returns to main at the line just after that call. The same pattern repeats for the second and third calls. The body of printTable was written once, but it ran three times, each time with a different value for n.

Worked Example: Reading a Two-Parameter Header

Worked example

What does this header promise?

Read the header public static double average(double x, double y) and state what a caller must supply and what the caller receives.

  1. 1
    Modifiers

    public and static appear before the return type. They set access and class-level characteristics, not the values involved.

  2. 2
    Return type

    The word double sits before the name. Because it is a type name rather than void, this subroutine is a function, and a double value comes back to the caller.

  3. 3
    Name

    The name is average. Callers use it to make the call.

  4. 4
    Parameter list

    Two parameters appear inside the parentheses, separated by a comma. Each has its own type: double x and double y.

  5. 5
    Caller's obligation

    A caller must supply two double values, in order, such as average(3.0, 5.0).

Result

Callers must pass two double values and should expect one double value back. The body of average is not needed to know this.

Mistakes When Writing Headers

  • Common mistake

    Listing several parameters with one shared type

    What it looks like
    public static double average(double x, y)
    Why it fails

    Each parameter needs its own type. The declaration gives no type for y.

    Do this instead
    public static double average(double x, double y)
  • Common mistake

    Expecting a value from a void subroutine

    What it looks like
    double result = printTable(3);
    Why it fails

    The void return type promises that no value comes back, so there is nothing to store.

    Do this instead

    Call printTable(3) on its own line, and use a function with a non-void return type when a value is needed.

  • Common mistake

    Using a modifier to describe values

    Why it fails

    Modifiers set characteristics such as static or public. The values a subroutine accepts and returns come from the parameter list and the return type.

  • Common mistake

    Reading the body before the header

    Why it fails

    The header states how the subroutine can be used, so reading it first tells you what to expect from the body and what to supply when you call it.

Subroutines in ThreeN2.java

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 gives two reasons for this design. 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.

Practice Reading Headers

EASY

Here is a header: public static void showPair(String label, int value). Without reading any body, state (a) what the subroutine hands back to its caller, (b) how many inputs a caller must supply and of what types, and (c) what the name of the first parameter is. Then write a main method that calls showPair twice with different arguments, and predict how many lines the program prints before you run it.

Hints
  • Look at the word before the name to answer part (a).
  • Count the declarations inside the parentheses, and read each one as type followed by name.
  • Each call to showPair runs its body once, so two calls mean two runs of the body.

Key Takeaways

  • A subroutine is a block of code that can be called multiple times from different parts of a program, and it runs only when the program calls it.
  • Read a header left to right: modifiers such as static and public set characteristics, the return type says what comes back, and the parameter list says what must be supplied.
  • A function's return type names the type of value returned, while void means the subroutine hands no value back to its caller.
  • Each parameter in a list needs its own type, written as type followed by name, such as double x, double y.
  • ThreeN2.java uses subroutines to organize its code and to format its output in neat columns.