Strings in Java

A string in java is a sequence of characters, for e.g. “Apple” is a string containing a sequence of five characters 'A', 'p', 'p', 'l', and 'e'. We use double quotes to represent a string in Java, like "Hello World".

In Java programming language, strings are treated as objects (not like a primitive data type). A string is an immutable object in Java, which means it is constant and cannot be changed once it has been created. Java provides "String" class to create and manage a string which implements implements Serializable, Comparable and CharSequence interfaces.

How to Create Strings in Java

We can create a Java String in two ways:

String Literal

In Java, a String can be created by assigning a String literal to a String instance.

String str1 = "Hello";
String str2 = "Hello";

Whenever a String object is created as a string literal, the object will be created in String constant pool. This allows JVM to optimize the initialization of String literal. Whenever you create a new string using the string literal method, the JVM will search for the String in the String Pool. If the String exists, then JVM will return the reference to the String.

There is a problem in this approach. As I stated earlier that String is an object in Java. However we have not created any string object using new keyword above approach. The compiler does that task for us it creates a string object having the string literal (which is "Hello", in this example) and assigns it to the provided String instances, but if the object already exist in the memory it does not create a new Object rather it assigns the same old object to the new instance, that means even though we have two string instances (str1 and str2 in above example) compiler only created on String object in String constant pool and assigned the same to both String instance variables.

What if we want to have two different String object in memory with the same character sequence, then we have to create strings using new keyword.

Using New Keyword

In this method, we use the "new" keyword to create an instance of String object. We will be following the syntax mentioned below to create a unique String object

String str3 = new String("Hello");
String str4 = new String("Hello");

In this approach, the string objects are created in the heap memory space instead of the string constant pool. Both str3 and str4 String instances will point to their unique String object in memory.

public class JavaString {
    public static void main(String[] args)
    {
        // Declare String using string literal
        String str1 = "TechCrashCourse";

        // Declare String using new operator
        String str2 = new String("TechCrashCourse");

        // Prints the String.
        System.out.println("String str1 = " + str1);
        System.out.println("String str2 = " + str2);
    }
}
Output
String str1 = TechCrashCourse
String str2 = TechCrashCourse

Below image illustrates the process of creating strings using both the above methods. Java String Memory Allocation
Creating Formatted Strings
String class has an static method called format()to print formatted string. It returns a String object rather than a PrintStream object.

Example
String result;
result = String.format("The total score of a player is %d ," +
                  "while the average score is %d", totalScore, averageScore);
System.out.println(result); 

Java Strings are Immutable

Strings in Java are immutable. This means, it cannot be changed once it is created. Let's understand this with an example:

// Creation of a String
String test = "Apple";
Here, we have created a string variable named test. The variable holds the string "Apple". Now suppose we want to append a string " Pie" at the end of string variable test.
test = test.concat(" Pie");
Here, we are using the concat() method to concatenate " Pie" string with initial string "Apple" to get final string as "Apple Pie". Here, it looks like we are able to change the content of the original string variable "test" but this is incorrect. Instead, JVM created a new string by combining two strings.

Here is how string concatenation happened here,
  1. JVM first created a new string "Apple" and assigned it to variable test.
  2. JVM then created a new string by concatenating "Apple" and "Pie". Remember, the content of original string test is unchanged.
  3. JVM then assiged the new string "Apple Pie" to the test variable.

Why Java Strings are Immutable

As Java uses the concept of String literal. Suppose there are three String reference variables, all refer to same String object "Orange". If one reference variable changes the value of the object, it will be update the String value for all three reference variables. That is why String objects in Java are.

Benefits of Immutable Strings in Java
  • String Pool is possible because String is immutable. Hence saving memory and fast performance.
  • Class loading is more secure since the string value passed as an argument to load a class can’t be changed.
  • Thread safety while working with strings in a multi-threaded environment.
  • More secure since we can’t change the value of string object.

Overview of Java String Class

  • Java String Class is present in java.util package.
  • A string is a sequence of characters. But, it’s not a primitive data type but an object.
  • String object is immutable in Java. So once created, we can’t change it.
  • String has a shortcut way to create its objects using double quotes. These string objects are also called string literals.
  • String is the only java class that supports operator overloading. We can use the ‘+’ operator to concatenate two strings.
  • Java store string objects in a specific pre-defined area. String pool is the part of java heap space to store string literals
Why String class is Final in Java ?

The reason behind the String class being final is because no one can override the methods of the String class. So that it can provide the same features to the new String objects as well as to the old ones.

Java String Class Methods

Java String class provides various methods to perform different operations on strings.

  • length(): Returns the length of the string object.
  • concat(String str): Concatenates the given string to the end of this string and return it.
  • substring(int beginIndex, int endIndex): Returns a substring of this string.
  • charAt(int index): Returns the character value at the given index.
  • toCharArray(): This method creates a character array from this string.
  • replace(char oldChar, char newChar): Returns a new string after replacing oldChar with the newChar.
  • getBytes(String charsetName): Used to create a byte array from this string.
  • compareTo(String anotherString): Compares this string to another string lexicographically. The comparison is case-sensitive.
  • compareToIgnoreCase(String str): Compares this string to another string lexicographically. The method performs case insensitive comparison.
  • equals(Object anObject): Used to compare this string with another object.
  • equalsIgnoreCase(String anotherString): Used to compare this string with another string case-insensitively.
  • startsWith(String prefix): Returns true if this string starts with the given string.
  • endsWith(String suffix): Returns true if this string ends with the given string.
  • matches(String regex): Checks whether this string matches the given regular expression.
  • join(CharSequence delimiter, CharSequence... elements): A utility method to join many strings into a new string with the specified delimiter. We can use this method to create a CSV record from the array of strings.
  • split(String regex): Splits this string into a string array using the regular expression argument.
  • toLowerCase(): Used to get the lowercase version of this string.
  • toUpperCase(): Used to get the uppercase version of this string.
  • trim(): Used to remove leading and trailing whitespaces from this string.
  • strip(): Returns new string after stripping white spaces from this string.
  • isBlank(): Returns true if the string is empty or contains only white spaces.
  • format(String format, Object... args): Returns a formatted string using the specified format and arguments.
  • valueOf(Object obj): Returns the string representation of the given object. There are overloaded versions to work with primitive data types, arrays, and objects.

How to Find Length of a String

To find the length of a string, we use the length() method of the String class.

public class StringLength {
    public static void main(String[] args) {
        // Creation of a string
        String str1 = "TechCrashCourse";

        // Print length of str1
        int length = str1.length();
        System.out.println(String.format("Length of %s is %d", 
                str1, length));
    }
}
Output
Length of TechCrashCourse is 15

How to Concatenate Two Strings in Java

We will join two strings using concat() method of String class.

public class ConcatenateString {
    public static void main(String[] args) {
        // Create first string
        String str1 = "Apple";
        System.out.println("First String: " + str1);

        // Create second string
        String str2 = " Pie";
        System.out.println("Second String: " + str2);

        // Concatenate two strings
        String joinedString = str1.concat(str2);
        System.out.println("Joined String: " + joinedString);
    }
}
Output
First String: Apple
Second String:  Pie
Joined String: Apple Pie

Conclusion

Understanding how to work with strings is fundamental for Java developers. From basic operations like concatenation and substring extraction to more advanced manipulations, strings are integral to many programming tasks. As you continue your journey in Java development, practice using strings in diverse scenarios, and explore the rich set of methods and techniques available for effective string handling.