Classes and Subroutines in Java
Text blocks provide a readable Java 17 syntax for multiline strings.
Keeping Multiline Text Readable
Two ideas in programming look unrelated at first: writing a long piece of text inside a program, and reusing a job that the program needs in several places. This article covers both. The first part explains Java 17 text blocks, a syntax for multiline strings that is easier to read than an ordinary string literal. The second part explains subroutines, blocks of code that can be called multiple times from different parts of a program.
Before reading on, try this question. Suppose a program needs the same calculation or the same printed output in three different places. Would you rather keep the instructions in one place and let the program use them whenever needed, or write them out in every place they are needed? Hold that answer in mind. The main idea of subroutines is an answer to exactly this question.
What do you think happens?
In a text block, is the newline that follows the opening delimiter part of the string value?
Reveal answer
No, it is excluded from the string value
The source states that the newline after the opening delimiter is excluded from the string value, so the text begins on the first content line.
Opening and Closing Delimiters
A text block begins with an opening delimiter made of three double quotation marks. It ends with a closing delimiter, also made of three double quotation marks. Everything between the two delimiters is the text. The text block is assigned to a String variable just as an ordinary string literal would be, and the result is still a string value, so Java code can use it wherever a normal string literal is accepted.
Read the diagram from left to right. Only the first and last items are delimiters. The middle items are where the text lives, and the newline immediately after the opening delimiter is not counted as part of the value.
- The opening delimiter is followed only by a newline, with nothing else on that line.
- The text lines are laid out across several source lines for readability.
- The closing delimiter marks where the text block stops.
- The whole text block is assigned to the String variable poem.
What Counts as Text Content
Two rules decide what ends up in the string. First, the whitespace and newline right after the opening delimiter are excluded, so the value starts at the first content line. Second, Java removes common leading whitespace from the text-block lines. This lets you indent the source code to match the surrounding program, without that indentation being automatically preserved in the value.
The before side shows the code as you would lay it out in your editor. The after side shows the text the program actually holds. The shared indentation disappears from the value, while the words themselves are kept. The point is that the layout you choose for readability in the source file is not forced into the data.
Mistakes with the Opening Line
A text block can look like an ordinary string literal that has simply been given extra quotation marks. That impression leads to the most common error, which is trying to start the text on the same line as the opening delimiter. Java 17 text blocks follow a stricter layout rule than that impression suggests.
Common mistake Placing the first words immediately after the opening three double quotes
What it looks likeString s = """Roses are redWhy it failsThe opening delimiter may be followed only by optional spaces or tabs and then a newline. Text on the same line breaks that layout rule.
Do this insteadPut the opening delimiter alone at the end of its line, then begin the text on the next line.
Common mistake Expecting the newline after the opening delimiter to appear in the value
What it looks likeAssuming the string starts with a blank line
Why it failsThe newline after the opening delimiter is excluded from the string value.
Do this insteadExpect the value to begin with the first content line.
Common mistake Assuming source indentation is kept exactly in the value
What it looks likeIndenting every line by several spaces to match the surrounding code
Why it failsJava removes common leading whitespace from the text-block lines, so the source indentation is not automatically preserved in the value.
Do this insteadIndent the source freely for readability and check the value to see what was actually kept.
Writing a Job Once: Subroutines
A subroutine is a block of code that can be called multiple times from different parts of a program.
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.
The important word 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.
Tracing Calls Through One Run
The example below is an original illustration, not taken from the source. A subroutine named printLine prints a divider line. The main part of the program prints a message, calls printLine, prints another message, calls printLine again, and then repeats the pattern once more. The subroutine is written once but runs three times.
Start
----
Middle
----
End
----printLineis written once and contains the divider code.- Each
printLine()call in main makes the program run the subroutine at that point. - The output shows the divider appearing after each call.
Following the Control Flow
In the Greeting program, which lines run, and in what order, after the program starts?
- 1Line 1 of main runs
The program prints Start.
- 2First call
The program reaches
printLine()and transfers control to the subroutine, which prints a divider. - 3Return
After the subroutine finishes, the program continues in main at the line after the call.
- 4Second and third calls
The same subroutine runs again after Middle and again after End, each time returning to main.
The output is Start, divider, Middle, divider, End, divider. One subroutine serves three moments in a single run.
Where ThreeN2.java Uses Subroutines
The source points to a concrete program that uses subroutines: ThreeN2.java. 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 using subroutines in this program. The first is code organization: separating work into named blocks makes the program easier to read and manage. The second is output formatting: subroutines are part of how the results are printed in neat columns.
The source does not list the individual subroutines inside ThreeN2.java or show their code, so this article does not describe them in detail. When you open the file yourself, look for the places where the program calls a named block of code, and compare them with the places where it prints results. Note which calls handle the computation and which handle the printed layout.
Practice Tracing Calls
In the Greeting program, change main so that printLine is called four times, once after each of the messages Start, Middle, End, and one additional message named Finish. Predict the complete output before you run the program. Then trace how many times the subroutine runs and where control returns after each call.
Hints
- Count the calls to
printLine, not the number of lines in the subroutine. - After each
printLine()call, control returns to the line that follows it in main. - The divider should appear after every message you print in main.
Write a text block that holds three lines of your own choosing. Put the opening delimiter alone on its line, indent the text lines to match your code, and close the block on its own line. Then state, without running it, where the string value begins.
Hints
- The value does not begin with the newline after the opening delimiter.
- Shared leading whitespace is removed from the lines.
Summary of Text Blocks and Subroutines
- 1A Java 17 text block opens with three double quotation marks followed only by optional spaces or tabs and a newline, and it closes with three double quotation marks.
- 2The newline after the opening delimiter is excluded from the string value, and common leading whitespace is removed from the text-block lines.
- 3A subroutine is a block of code that runs when the program calls it, so one written block can be reused at many points in a run.
- 4
ThreeN2.javauses subroutines to organize its code and to help format its output in neat columns.
At a glance
- A Java 17 text block is delimited by three double quotation marks, with the opening delimiter followed only by optional spaces or tabs and a newline.
- The newline after the opening delimiter is not part of the string value, and common leading whitespace is removed from the text-block lines.
- 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.
- Subroutines help organize code and format output, which is why
ThreeN2.javauses them.