Book Image

Java Coding Problems - Second Edition

By : Anghel Leonard
Book Image

Java Coding Problems - Second Edition

By: Anghel Leonard

Overview of this book

The super-fast evolution of the JDK between versions 12 and 21 has made the learning curve of modern Java steeper, and increased the time needed to learn it. This book will make your learning journey quicker and increase your willingness to try Java’s new features by explaining the correct practices and decisions related to complexity, performance, readability, and more. Java Coding Problems takes you through Java’s latest features but doesn’t always advocate the use of new solutions — instead, it focuses on revealing the trade-offs involved in deciding what the best solution is for a certain problem. There are more than two hundred brand new and carefully selected problems in this second edition, chosen to highlight and cover the core everyday challenges of a Java programmer. Apart from providing a comprehensive compendium of problem solutions based on real-world examples, this book will also give you the confidence to answer questions relating to matching particular streams and methods to various problems. By the end of this book you will have gained a strong understanding of Java’s new features and have the confidence to develop and choose the right solutions to your problems.
Table of Contents (16 chapters)
1
Text Blocks, Locales, Numbers, and Math
Free Chapter
2
Objects, Immutability, Switch Expressions, and Pattern Matching
14
Other Books You May Enjoy
15
Index

42. Adding code snippets in Java API documentation

I’m sure that you are familiar with generating Java API documentation (Javadoc) for your projects. We can do it via the javadoc tool from the command line, via IDE support, via the Maven plugin (maven-javadoc-plugin), and so on.

A common case in writing the Javadoc consists of adding snippets of code to exemplify the usage of a non-trivial class or method. Before JDK 18, adding snippets of code in documentation can be done via {@code...} or the <pre> tag. The added code is treated as plain text, is not validated for correctness, and is not discoverable by other tools. Let’s quickly see an example:

/**
 * A telemeter with laser ranging from 0 to 60 ft including   
 * calculation of surfaces and volumes with high-precision
 *
 * <pre>{@code
 *     Telemeter.Calibrate.at(0.00001);
 *     Telemeter telemeter = new Telemeter(0.15, 2, "IP54");
 * }</pre>
 */
public class Telemeter {
   ...

In the bundled code, you can see the full example. The Javadoc is generated at build time via the Maven plugin (maven-javadoc-plugin), so simply trigger a build.

Starting with JDK 18 (JEP 413 - Code Snippets in Java API Documentation), we have brand new support for adding snippets of code in documentation via the {@snippet...} tag. The code added via @snippet can be discovered and validated by third-party tools (not by the javadoc tool itself).

For instance, the previous snippet can be added via @snippet as follows:

/**
 * A telemeter with laser ranging from 0 to 60 ft including   
 * calculation of surfaces and volumes with high-precision
 *
 * {@snippet :
 *     Telemeter.Calibrate.at(0.00001);
 *     Telemeter telemeter = new Telemeter(0.15, 2, "IP54");
 * }
 */
public class Telemeter {
   ...

A screenshot of the output is in the following figure:

Figure 2.13.png

Figure 2.13: Simple output from @snippet

The effective code starts from the newline placed after the colon (:) and ends before the closing right curly bracket (}). The code indentation is treated as in code blocks, so the compiler removes the incidental white spaces and we can indent the code with respect to the closing right curly bracket (}). Check out the following figure:

Figure 2.14.png

Figure 2.14: Indentation of code snippets

In the top example, the closing right curly bracket is aligned under the opening left curly bracket, while in the bottom example, we shifted the closing right curly bracket to the right.

Adding attributes

We can specify attributes for a @snippet via name=value pairs. For instance, we can provide a tip about the programming language of our snippet via the lang attribute. The value of the attribute is available to external tools and is present in the generated HTML. Here are two examples:

 * {@snippet lang="java" :
 *     Telemeter.Calibrate.at(0.00001);
 *     Telemeter telemeter = new Telemeter(0.15, 2, "IP54");
 * }

In the generated HTML, you’ll easily identify this attribute as:

<code class="language-java"></code>

If the code is a structured text such as a properties file, then you can follow this example:

 * {@snippet lang="properties" :
 *   telemeter.precision.default=42
 *   telemeter.clazz.default=2
 * }

In the generated HTML, you’ll have:

<code class="language-properties"></code>

Next, let’s see how can we alter what is displayed in a snippet.

Using markup comments and regions

We can visually alter a snippet of code via markup comments. A markup comment occurs at the end of the line and it contains one or more markup tags of the form @name args, where args are commonly name=value pairs. Common markup comments include highlighting, linking, and content (text) modifications.

Highlighting

Highlighting a whole line can be done via @highlight without arguments, as in the following figure:

Figure 2.15.png

Figure 2.15: Highlighting a whole line of code

As you can see in this figure, the first line of code was bolded.

If we want to highlight multiple lines, then we can define regions. A region can be treated as anonymous or have an explicit name. An anonymous region is demarcated by the word region placed as an argument of the markup tag and the @end tag placed at the end of the region. Here is an example for highlighting two regions (an anonymous one and a named one (R1)):

Figure 2.16.png

Figure 2.16: Highlighting a block of code using regions

Regular expressions allow us to highlight a certain part of the code. For instance, highlighting everything that occurs between quotes can be done via @highlight regex='".*"'. Or, highlighting only the word Calibrate can be done via the substring="Calibrate" argument, as in the following figure:

Figure 2.17.png

Figure 2.17: Highlighting only the word “Calibrate”

Next, let’s talk about adding links in code.

Linking

Adding links in code can be done via the @link tag. The common arguments are substring="…" and target="…". For instance, the following snippet provides a link for the text Calibrate that navigates in documentation to the description of the Calibrate.at() method:

Figure 2.18.png

Figure 2.18: Adding links in code

Next, let’s see how we can modify the code’s text.

Modifying the code’s text

Sometimes we may need to alter the code’s text. For instance, instead of Telemeter.Calibrate.at(0.00001, "HIGH");, we want to render in documentation Telemeter.Calibrate.at(eps, "HIGH");. So, we need to replace 0.00001 with eps. This is the perfect job for the @replace tag. Common arguments include substring="…" (or, regex="…") and replacement="...". Here is the snippet:

Figure 2.19.png

Figure 2.19: Replacing the code’s text

If you need to perform multiple replacements in a block of code, then rely on regions. In the following example, we apply a regular expression to a block of code:

Figure 2.20.png

Figure 2.20: Applying multiple replacements via a simple regex and an anonymous region

If you need to perform more replacements on the same line, then just chain multiple @replace tags (this statement applies to all tags such as @highlight, @link, and so on).

Using external snippets

So far, we have used only inlined snippets. But, there are scenarios when using inlined snippets is not a convenient approach (for instance, if we need to repeat some parts of the documentation) or it is not possible to use them (for instance, if we want to embed /*…*/ comments, which cannot be added in inlined snippets).

For such cases, we can use external snippets. Without any further configurations, JDK automatically recognizes external snippets if they are placed in a subfolder of the package (folder) containing the snippet tag. This subfolder should be named snippet-files and it can contain external snippets as Java sources, plain text files, or properties files. In the following figure, we have a single external file named MainSnippet.txt:

Figure 2.21.png

Figure 2.21: External snippets in snippet-files

If the external snippet is not a Java file, then it can be loaded via {@snippet file …} as follows:

{@snippet file = MainSnippet.txt}
{@snippet file = "MainSnippet.txt"}
{@snippet file = 'MainSnippet.txt'}

But, we can also customize the place and folder name of external snippets. For instance, let’s place the external snippets in a folder named snippet-src, as follows:

Figure 2.22.png

Figure 2.22: External snippets in a custom folder and place

This time, we have to instruct the compiler where to find the external snippets. This is done by passing the --snippet-path option to javadoc. Of course, you can pass it via the command line, via your IDE, or via maven-javadoc-plugin, as follows:

<additionalJOption>
  --snippet-path C:\...\src\snippet-src
</additionalJOption>

This path is relative to your machine, so feel free to adjust it accordingly in pom.xml.

Next, AtSnippet.txt and ParamDefaultSnippet.properties can be loaded exactly as you saw earlier for MainSnippet.txt. However, loading Java sources, such as DistanceSnippet.java, can be done via {@snippet class…}, as follows:

{@snippet class = DistanceSnippet}
{@snippet class = "DistanceSnippet"}
{@snippet class = 'DistanceSnippet'}

But, do not add explicitly the .java extension because you’ll get an error such as file not found on source path or snippet path: DistanceSnippet/java.java:

{@snippet class = DistanceSnippet.java}

When using Java sources as external snippets, pay attention to the following note.

Important note

Even if the predefined snippet-files name is an invalid name for a Java package, some systems may treat this folder as being part of the package hierarchy. In such cases, if you place Java sources in this folder, you’ll get an error such as Illegal package name: “foo.buzz.snippet-files”. If you find yourself in this scenario, then simply use another folder name and location for the documentation external snippets written in Java sources.

Regions in external snippets

The external snippets support regions via @start region=… and @end region=…. For instance, in AtSnippet.txt, we have the following region:

// This is an example used in the documentation
// @start region=only-code 
   Telemeter.Calibrate.at(0.00001, "HIGH");  
// @end region=only-code

Now, if we load the region as:

{@snippet file = AtSnippet.txt region=only-code}

We obtain only the code from the region without the text, // This is an example used in the documentation.

Here is another example of a properties file with two regions:

# @start region=dist
sc=[0,0]
ec=[0,0]
interpolation=false
# @end region=dist
# @start region=at
eps=0.1
type=null
# @end region=at

The region dist is used to show the default values for the arguments of the distance() method in the documentation:

Figure 2.23.png

Figure 2.23: Using the dist region

And, the at region is used to show the default values for the arguments of the at() method in the documentation:

Figure 2.24.png

Figure 2.24: Using the “at” region

In external snippets, we can use the same tags as in the inlined snippets. For instance, in the following figure, you can see the complete source of AtSnippet.txt:

Figure 2.25.png

Figure 2.25: Source of AtSnippet.txt

Notice the presence of @highlight and @replace.

Important note

Starting with JDK 19, the Javadoc search feature was also improved. In other words, JDK 19+ can generate a standalone search page for searching in the Javadoc API documentation. Moreover, the search syntax has been enhanced to support multiple search words.

You can practice these examples in the bundled code.