Java String

String is one of the most widely used class in Java. Part of java.lang package, the String class represents character strings. Strings receive special treatment in Java, because they are used frequently in a program

  • String is associated with string literal in the form of double-quoted texts such as "Hello, Java!". You can assign a string literal directly into a String variable, instead of calling the constructor to create a String instance.
  • The '+' operator, which performs addition on primitives (such as int and double), is overloaded to operate on String objects. '+' performs concatenation for two String operands.
  • String is immutable. That is, its content cannot be modified once it is created. For example, the method replace(...), substring(...), toUpperCase(), etc constructs and returns a new String instead of modifying the its existing content.

Creating a String

There are two data types in Java: primitive types and reference types. Primitive types contains only value and stored in the call stack. This means primitive types require less storage spaces (and size is fixed) and are cheaper to manipulate. On the other hand, objects (instance of a class) are stored in the program heap, they reference a memory location, which stores the data. This is require complex memory management and more storage spaces. For performance reason, Java's String is designed to be in between a primitive and a class.

A String can be constructed by either:

  • directly assigning a string literal to a String reference (just like a primitive)
  • via the "new" operator and constructor, similar to any other classes.

For example:

// Implicit literal
String slit = "Hello, Java";

// Explicit new
String snew = new String("Dariawan Blog");

In the first statement, slit is declared as a String reference and initialized with a string literal "Hello, Java". In the second statement, snew is declared as a String reference and initialized via the new operator and constructor to contain "Dariawan Blog". However, creating String using "new" operator is not recommended, why?

String Literal vs. String New

String Constant Pool

String Constant Pool

Java has provided a special mechanism for keeping the String literals, called string constant pool. If two string literals have the same contents, they will share the same storage inside the string pool, to conserve storage for frequently-used strings. On the other hand, String objects created via the new operator and constructor are kept in the heap. Just like any other object, each String object in the heap has its own storage. There is no sharing of storage in heap even if two String objects have the same contents.

you can use the method equals() of the String class to compare the contents of two Strings. You can use the relational equality operator '==' to compare the references (or pointers) of two objects.

String s1 = new String("java");  // new object
String s2 = new String("java");  // new object
String s3 = "java";              // literal
String s4 = "java";              // literal

System.out.println(s1 == s2);       // false, different pointers
System.out.println(s1.equals(s2));  // true, same contents
System.out.println(s1.equals(s3));  // true, same contents
System.out.println(s1 == s4);       // false, different pointers
System.out.println(s1.equals(s4));  // true, same contents
System.out.println(s3 == s4);       // true, s3 and s4 share storage in constant pool
System.out.println(s3.equals(s4));  // true, same contents

for equals(...) and '==' let's talk about String comparison...

String Compare

String class provides equals(...) and equalsIgnoreCase(...) methods to compare two strings:

String s1 = "xyz";
String s2 = "xyz";
String s3 = "XYZ";

System.out.println(s2.equals(s3));                // false
System.out.println(s1.equalsIgnoreCase(s3));      // true
System.out.println(s1.equals(s3.toLowerCase()));  // true

And we know that '==' operator will refer to pointers of two objects:

String s1 = "xyz";
String s2 = "xyz";
String s3 = "XYZ";

System.out.println(s1 == s2);                // true
System.out.println(s2 == s3);                // false
System.out.println(s1 == s3.toLowerCase());  // false

As you can see, s1 == s3.toLowerCase() resulting false, since although s3 already lowered-case, the '==' will refer to the pointer of s3 which is is not the same pointer as s1.

String class implements Comparable interface, which provides compareTo() method. Besides compareTo() String also have compareToIgnoreCase() method:

The comparison is based on the Unicode value of each character in the strings. The character sequence represented by this String object is compared lexicographically to the character sequence represented by the argument string. If strings are equal then it returns zero or else it returns either greater or less than zero.

String s1 = "xyz";
String s2 = "xyz";
String s3 = "XYZ";

System.out.println(s1.compareTo(s2));            // 0
System.out.println(s2.compareTo(s3));            // 32 -> greater than 0
System.out.println(s3.compareTo(s1));            // -32 -> less than 0       
System.out.println(s1.compareToIgnoreCase(s3));  // 0

String Concatenation

String can be concatenated by using “+” operator or by using concat() method.

String s1 = "ping";
String s2 = "pong";

// + operator
System.out.println(s1 + s2);        // pingpong

// concat method
System.out.println(s1.concat(s2));  // pingpong

String Length

Use length method to get the number of characters in a String.

  • int length(): Returns the length of this string.
String s = "Good morning!";
System.out.println(s.length());  // length is 13


Substring methods will returns part of the string based on specified indexes.

String s = "Greetings, developer!";
s = s.substring(11);
System.out.println(s);  // developer!

s = s.substring(3, 7);  // from "developer!"
System.out.println(s);  // elop

String Index

String index is started from 0, and last index is length - 0. We can use method charAt(...) to get the char at respective index.

String s = "Dariawan";
char c1 = s.charAt(0);
System.out.println(c1 == 'D');  // true

char c2 = s.charAt(s.length()-1);
System.out.println(c2 == 'n');  // true

methods indexOf(...) or lastIndexOf​(...) of a String also utilize this index.

String s = "Dariawan";

System.out.println(s.indexOf("ria"));   // r start from 2
System.out.println(s.indexOf('a', 2));  // 'a' after index 2 (r) is in 4
System.out.println(s.lastIndexOf('a')); // last index of 'a' is 6

String Methods

Following example using various methods of String available in Java 8:

String s1 = "xyz";
String s2 = "XYZ";

// All are Java 8 methods:
System.out.println(s1==s2);                   // compares reference address - false
System.out.println(s1.equals(s2));            // compares the values - false
System.out.println(s1.equalsIgnoreCase(s2));  // compares the values ignoring the case - true
System.out.println(s1.length());              // calculates length - 3
System.out.println(s1.charAt(1));             // extract 2nd character - y
System.out.println(s1.toUpperCase());         // returns string in ALL CAPS - XYZ
System.out.println(s2.toLowerCase());         // returns string in ALL lowercase - xyz
System.out.println(s1.replace("y", "Y"));     // search and replace "y" with "Y" - xYz
System.out.println(s1.trim());                // trims surrounding whitespace - xyz
System.out.println(s1.contains("yz"));        // check for the values "yz" - true
System.out.println(s1.toCharArray());         // convert String to aray of characters - xyz
System.out.println(s1.isEmpty());             // Check if String is empty - false
System.out.println(s1.endsWith("."));         // Checks if string ends with "." - false

This article is part of Java Data Types Series.

Other articles in this series:

This article also part of following series: