Java strings tutorial

In this article I am going to teach you about basics of Java strings.

Strings contain sequences of characters. It can be a single character (ie. “a”) as well as long sequences consisting from many characters (ie. “a longer string example”). Strings are very important and very common element of Java (as well as many other languages), therefore it is very important to understand them very well.

Creating Java strings

There are two basic methods of creating strings. While there are other more complex methods like StringBuilder, they all internally use one of those two methods.

String literals

This is the most basic method of creating strings. It uses a String literal to create a new string. String literals are built by enclosing a string within double quotes, for example “this is a string literal”.

String myCat = "Fritz";
String myName = "Adam Scheller";
String letter = "b";
// Displaying a string on the screen using string literal
System.out.println("This is a string literal");

New String object

This method involves creating a new String object using the new keyword, for example new String(“my string”).

String myCat = new String("Fritz");
String myName = new String("Adam Scheller");
String letter = new String("b");

// Displaying a string on the screen using new String object
System.out.println(new String("This is a new String object"));

Difference between string literals and creating new String objects

While the two methods described above look like doing exactly the same thing, it isn’t completely true. There is one significant difference between those two methods that affect the way how created string is stored in the computer memory.

The strings created using a string literal are being stored in the so called string pool. It’s a special place in the computer memory where all strings created through literals are stored. The characteristic of the string pool is that it does not contain any duplicate strings. When you create a string for the first time using a literal, it is being saved in the string pool. When you create a string through a literal with the same content again somewhere in your program, Java simply reuses the already existing string in the string pool. Strings in the string pool live thorough entire life of the program and are not garbage collected.

The strings created using the new keyword are being stored on the heap, a special place in the memory where all Java objects are stored. Creating strings with the new keyword will always create a new object on the heap, even if a string with the same content was created before. Objects on the heap are subject to garbage collection.

Comparing Java strings

Strings are very often compared to other strings, therefore it’s important to understand this concept very well, especially because it may be tricky for the beginners.

The first thing that may come to your head is that you can compare two strings using the compare operator ==. This is wrong and comparisons should never be done that way. Take a look at the example below to find out why:

String a = "my string";
String b = "my string";
System.out.println( a == b ); // prints "true"

String c = new String("my string");
String d = new String("my string");
System.out.println( c == d ); // prints "false"

System.out.println( a == c ); // prints "false

All of the strings in the code above contain the same “my string” value, but not every of the comparisons returns true when using the == operator. Why?

As strings are objects, the == operator compares their reference to memory. String literals containing the same value will refer to the same place in computer memory, therefore making checks with == operator return true. Strings created using the new keyword will always create a new object having different reference to memory, therefore comparisons with == operator will always return false.

To compare strings using their value and not their references, you have to use the built-in equals method:

String a = new String("my string");
String b = new String("my string");
System.out.println( a.equals(b) ); // prints "true"

Remember to always compare your strings using the equals method, even if you compare only literals!

Java strings methods

Strings are objects, and objects can contain methods inside. String objects contain many useful methods that make working with strings much easier. I will explain here a few of the most commonly used String methods.

int length()

Returns length of the string. Technically, length is amount of Unicode code points in a string.

String test1 = "cat";
System.out.println(test1.length()); // -> 3

String test2 = "猫";
System.out.println(test2.length()); // -> 1

boolean isEmpty()

Returns true is when the string is empty (length of the string is equal to 0).

String test1 = "";
System.out.println( test1.isEmpty() ); // -> true

String test2 = " ";
System.out.println( test2.isEmpty() ); // -> false; there is a space in the string

boolean contains(CharSequence s)

Returns true if the string contains the provided CharSequence. The CharSequence is a super-class of a String, so you can provide a String as an argument.

String test1 = "my sofa is gray";
System.out.println( test1.contains("sofa") ); // -> true

String test2 = "my sofa is gray";
System.out.println( test2.contains("chair") ); // -> false

boolean startsWith(String prefix)
boolean endsWith(String suffix)

Returns true when the string begins (startsWith) or ends (endsWith) with provided string.

String test = "Porsche 911 Turbo";
System.out.println( test.startsWith("Porsche") ); // -> true
System.out.println( test.startsWith("Trabant") ); // -> false
System.out.println( test.endsWith("Turbo") ); // -> true

boolean equals()
boolean equalsIgnoreCase()

Compares two strings, returns true when both strings contain the same content. The equalsIgnoreCase ignores letters case.

String test = "Mineral water";
System.out.println( test.equals("mineral water") ); // -> false; the case doesn't match
System.out.println( test.equalsIgnoreCase("mineral water") ); // -> true

int indexOf(String str)
int indexOf(String str, int fromIndex)

Returns position of the first occurence of str in the string. If the fromIndex parameter is provided, the search begins from the provided index.

String test = "My cat meows, because it is a cat";
System.out.println( test.indexOf("cat") ); // -> 3
System.out.println( test.indexOf("cat", 4) ); // -> 30

String concat(String str)

Concatenates (adds) two strings together and returns the result as a new string. Remember that strings are immutable, therefore no string gets modified.
As concat returns a String, concat methods can be chained.

String test = "My cat ";
String newStr = test.concat("is great ").concat("and catches mice");
System.out.println( newStr ); // -> My cat is great and catches mice

static String join(CharSequence delimiter, CharSequence… elements)
static String join(CharSequence delimiter, Iterable<? extends CharSequence>)

Joins strings together connecting them with a delimiter. Returns a new string as a result.
The first method signature accepts variable arguments. You can provide one or more arguments that you want to join together.
The second method signature accepts constructs like in example Lists.

System.out.println( String.join(", ", "cat", "mouse", "rat") ); // -> "cat, mouse, rat"

String[] arr = { "cat", "mouse", "rat" };
System.out.println( String.join(", ", arr) ); // -> "cat, mouse, rat"

List<String> list = new ArrayList<>();
System.out.println( String.join(", ", list) ); // -> "cat, mouse, rat"

String[] split(String regex)

Splits the string by matches of the provided regular expression.  Returns a String array as a result.

String test = "cat, mouse, rat";
String[] result = test.split(", ");
System.out.println( Arrays.toString(result) ); // -> [ "cat", "mouse", "rat" ]

String replace(CharSequence target, CharSequence replacement)

Replaces target values with replacement values in the string and returns the result as a new string.

String test = "My cat likes meat, because it is a cat";
String newStr = test.replace("cat", "dog");
System.out.println( newStr ); // -> "My dog likes meat, because it is a dog"

String substring(int beginIndex)
String substring(int beginIndex, int endIndex)

Extracts a part of the string and returns it as a new string. The beginIndex specifies the position to start the extraction and endIndex specifies the ending position. If endIndex is not provided, the ending position is end of the string.

String test = "This is a test string";
System.out.println( test.substring(8,14) ); // -> "a test"
System.out.println( test.substring(8) ); // -> "a test string"

String trim()

Removes any trailing or leading whitespace in the string and returns the result as a new string. Remember that strings are immutable, therefore no string gets modified.

String test = "   Test string ";
System.out.println( test.trim() ); // -> "Test string"

String toLowerCase()
String toUpperCase()

Changes all characters to either lowercase or uppercase and returns the result as a new string. Remember that strings are immutable, therefore no string gets modified.

String test = "This is a Test String";
System.out.println( test.toLowerCase() ); // -> "this is a test string"
System.out.println( test.toUpperCase() ); // -> "THIS IS A TEST STRING"

Learn more about Java