Core Java

Java 12 String Methods Example

In this article, we will discuss the new methods of the String class introduced in Java SE 12.

1. Introduction

The latest Java release (Java SE 12) arrives on the heels of
Java SE 11, due to the twice-annual release schedule. It is more akin to a
point release than a major release, with only minor changes from the previous
release.

Java SE 12 includes four new String methods.

  • String::indent
  • String::transform
  • String::describeConstable
  • String::resolveConstantDesc​

The indent and transform methods were introduced to support JEP 326 (Raw String Literals), which was eventually dropped from Java SE 12. Their chief purpose is to customize the alignment of Raw String Literals. (Another string method, align, was also dropped from Java SE 12.)

The describeConstable and resolveConstantDesc methods were introduced to support JEP 334 (JVM Constants API). These methods implement the Constable, and ConstantDesc interfaces, respectively. (The JVM Constants API allows loadable constants to be symbolically referenced. This change is technical in nature and is beneficial for programs that work with the constant pool table. For a short explanation on the Constants API, view the following article: Java 12’s JVM Constants API explained in 5 minutes.)

Only the first two methods are useful to the typical Java developer. In this article, we will give examples of all four methods for completeness.

1.1 Tools Used in this Example

  • Eclipse IDE for Enterprise Java Developers Version: 4.11.0
  • Java SE Development Kit 12.0.1
  • JUnit Version 4.12

2. Java 12 String Methods Example

2.1 Setup the Environment

Start by downloading the Java 12 JDK from the Oracle website. https://www.oracle.com/technetwork/java/javase/downloads/jdk12-downloads-5295953.html

Next, follow the instructions in the Installation Guide from the Oracle Help Center. https://docs.oracle.com/en/java/javase/12/install/overview-jdk-installation.html#GUID-8677A77F-231A-40F7-98B9-1FD0B48C346A

To configure Java 12 in Eclipse, select Preferences from the menu and type “jre” in the search box.  Select Installed JREs from the result list.

Java 12 String Methods - Java Runtime Environments
Installed Java Runtime Environments

Click on the Add… button.  In the JRE Type dialog window, select Standard VM and click Next.

Java 12 String Methods -  JRE Type
JRE Type

Click on the Directory… button and browse to the directory where you installed the Java 12 JDK. 

Java 12 String Methods - Add JRE
Add JRE

Click Finish and Apply and Close.

2.2 Create the JUnit Maven Project

Let’s create a simple Maven Project for our JUnit tests. Select “New” -> Maven Project” and select the “Create a simple project (skip archetype selection)” checkbox and click “Next”.

Java 12 String Methods - Maven Project
New Maven Project

Enter a Group Id, Artifact Id, and select “jar” for Packaging and click “Finish”.

Java 12 String Methods -  JUnit Test Projec
Create JUnit Test Project

Open the pom.xml file and add the following just below the versionelement.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  	<modelVersion>4.0.0</modelVersion>
  	<groupId>com.javacodegeeks.examples</groupId>
  	<artifactId>java-12-string-test</artifactId>
  	<version>0.0.1-SNAPSHOT</version>
  
     <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>12</source>
                    <target>12</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
     
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies> 
    
</project>

The maven-compiler-plugin will be used for building the project. The compiler is configured for Java SE 12. We also added the JUnit dependency.

Save the changes and select Maven->Update Project from the project context menu. Select your project from “Available Maven Codebases”. Leave the other defaults and click OK.

2.3 Configure Project for Java SE 12

An additional step is required to configure our project to use Java 12. Right-click the project and select Build Path > Configure Build Path. Select the Libraries tab. Remove the “J2SE-1.5 JRE” library and add the “jdk-12.0.1” JRE System library.

Add JRE 12 System Library

Click Finish and Apply and Close.

2.4 Create HTML Resource

We will be using an HTML file in some of the tests. Create the following file in the /src/test/resources folder. (You can copy it from the zip archive in the download section.)

helloworld.html

<html>
    <body>
        <p>Hello Code Geeks!</p>
    </body>
</html>

2.5 String::indent

The String::indent method will add or remove leading white space characters for each line of a single or multi-line String and return the result. White space characters include the tab character. Each line is then suffixed with a line feed (“\n”). A positive value passed to the method will insert spaces at the beginning of the line. A negative value will remove spaces. If the negative value specified is more than the available leading white space characters in the line, all leading white space characters are removed. The method was added to provide more control when aligning Raw String Literals.

Right-click the Java package under /scr/test/java and select New > Other… JUnit Test Case.  Click Next.  Enter the name “StringIndentTest” for the test case and click Finish

New JUnit Test

Add the following code to the StringIndentTest class.

StringIndentTest.java

import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Before;
import org.junit.Test;

public class StringIndentTest {

	String data_from_file;
	
	private String buildHTMLWithIndent() {
		StringBuilder html_string = new StringBuilder();
		html_string.append("    <html>\n");
		html_string.append("        <body>\n");
		html_string.append("            <p>Hello Code Geeks!</p>\n");
		html_string.append("        </body>\n");
		html_string.append("    </html>\n");
		return html_string.toString();
	}
	
	private String buildHTMLWithoutIndent() {
		StringBuilder html_string = new StringBuilder();
		html_string.append("<html>\n");
		html_string.append("<body>\n");
		html_string.append("<p>Hello Code Geeks!</p>\n");
		html_string.append("</body>\n");
		html_string.append("</html>\n");
		return html_string.toString();
	}
	
	@Before
	public void loadHTMLFile() throws URISyntaxException, IOException {
		Path path = Paths.get(getClass().getClassLoader().getResource("helloworld.html").toURI());
		Stream<String> lines = Files.lines(path);
		data_from_file = lines.collect(Collectors.joining("\n"));
		lines.close();
	}
	
	@Test
	public void test_remove_spaces() {
		System.out.println(data_from_file.indent(-12));
		assertTrue("strings do not match", data_from_file.indent(-12).equals(buildHTMLWithoutIndent()));
	}
	
	@Test
	public void test_add_spaces() throws URISyntaxException, IOException {
		System.out.println(data_from_file.indent(4));
		assertTrue("strings do not match", data_from_file.indent(4).equals(buildHTMLWithIndent()));
	}
	
}

We begin by declaring a class variable, data_from_file . Next, we add two helper methods buildHTMLWithIndent and buildHTMLWithoutIndent that will be used to build the HTML strings used in our tests.

The loadHTMLFile method loads the helloworld.html file and writes its contents to the data_from_file string variable. It will be executed before each test.

The test_remove_spaces test calls the indent method on the data_from_file string using the negative value “-12” as a parameter and asserts that it is equal to the string created by the buildHTMLWithoutIndent method.

The test_add_spaces test calls the indent method on the data_from_file string using the positive value “4” as a parameter and asserts that it is equal to the string created by the buildHTMLWithIndent method.

Right-click the test class and select Run As > JUnit Test. Both tests should pass.

JUnit Test Results

You will also see the following output in the console.

StringIndentTest Output

<html>
<body>
<p>Hello Code Geeks!</p>
</body>
</html>

    <html>
        <body>
            <p>Hello Code Geeks!</p>
        </body>
    </html>

2.6 String::transform

The motivation for String::transform was to permit custom alignment when working with Raw String Literals. It allows the programmer to apply a function to a string. The function will accept a String as an argument. The initial conception was that the function would return a String, but it was broadened to allow other return types. Let’s look at some examples.

Right-click the Java package under /scr/test/java and select New > Other… JUnit Test Case.  Click Next.  Enter the name “StringTransformTest” for the test case and click Finish

Add the following code to the StringTransformTest class.

StringTransformTest.java

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import org.junit.Test;

public class StringTransformTest {
	
	static Stream<String> sortList(String list) {
		return List.of(list.split(",")).stream().sorted();
	}


	@Test
	public void testTransfromPhrase() {
		String phrase = "this is a sentence";
		String sentence = phrase.transform(s -> s.substring(0, 1).toUpperCase() + s.substring(1) + ".");
		assertTrue("phrase was not transformed", sentence.equalsIgnoreCase("This is a sentence."));
	}

	@Test
	public void testTransfromToStream() {
		String fruits = "Kiwi,Banana,Apple";
		Stream<String> transformed = fruits.transform(StringTransformTest::sortList);
		Optional<String> result = transformed.findFirst();
		assertThat(result.get(), is("Apple"));
	}
}

First, we add a static method sortList that will serve as a function to one of the tests.

In the first test, we use a lambda expression to apply a function to this string phrase. The function changes the first character to uppercase and adds a period to the end of the string. We then make an assertion to that fact.

In the second test, we create a string with a comma separated list of fruits. In the transform method, we pass a method reference to the static sortList method, which returns a sorted Stream. Finally, we assert that the first fruit in the stream is “Apple”.

Right-click the class and select Run As > JUnit Test. Both tests should pass.

2.7 String::describeConstable and String::resolveConstantDesc

Two methods, describeConstable, and resolveConstantDesc were added to the String class to support the JVM Constants API, as discussed in the introduction section of this article.

The resolveConstantDesc(MethodHandles.Lookup lookup)
method resolves the String instance as a descriptor and returns the result,
which turns out to be the String instance itself.

The describeConstable method returns an Optional object that contains a descriptor for the String instance, which is also the String instance itself. Let’s look at examples of the two methods.

Right-click the Java package under /scr/test/java and select New > Other… JUnit Test Case.  Click Next.  Enter the name “StringConstableTest” for the test case and click Finish

Add the following code to the StringConstableTestclass.

StringConstableTest.java

import static org.junit.Assert.assertTrue;

import java.lang.invoke.MethodHandles;
import java.util.Optional;

import org.junit.Test;

public class StringConstableTest {

	@Test
	public void testResolveConstantDesc() {	
		String greeting = "Hello Geeks!";
		String constantDesc = greeting.resolveConstantDesc(MethodHandles.lookup());
		assertTrue(constantDesc.equals(greeting));
		System.out.println(constantDesc);
	}

	@Test
	public void testDescConstable() {
		String closing = "Goodbye Geeks!";
		Optional<String> opOfGreeting = closing.describeConstable();
		assertTrue(opOfGreeting.isPresent());
		assertTrue(opOfGreeting.get().equals(closing));
		System.out.println(opOfGreeting);
	}
}

The first test, testResolveConstantDesc calls the resolveConstantDesc(MethodHandles.lookup()) method on the greeting string. Then we test that the result is equal to the greeting string and print out the result.

The second test, testDescConstable, calls the describeConstable method on the closing string. Then we test that the result exists in the Optional object and that it is equal to the closing string. Finally, we print out the result.

Right-click the class and select Run As > JUnit Test. Both tests should pass.

You will also see the following output in the console.

StringConstableTest Output

Hello Geeks!
Optional[Goodbye Geeks!]

3. Java 12 String Methods – Summary

In this example, we discussed and tested the new methods of the String class introduced in Java version 12.

4. Download the Source Code

This was a Java 12 String Class New Methods Example.

Download
You can download the full source code of this example here:
Java 12 String Methods Example

Gilbert Lopez

Gilbert Lopez is an application developer and systems integration developer with experience building business solutions for large and medium-sized companies. He has worked on many Java EE projects. His roles have included lead developer, systems analyst, business analyst and consultant. Gilbert graduated from California State University in Los Angeles with a Bachelor of Science degree in Business.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button