String | String Constant Pool | String Immutable Concept | String Buffer | String Builder

String | String Constant Pool | String Immutable Concept | String Buffer | String Builder

In Java, the String class represents a sequence of characters. It is one of the most commonly used classes and provides various methods for manipulating strings.

Example: Creating and Manipulating Strings

    
      public class StringExample {
        public static void main(String[] args) {
          // Creating strings
          String greeting = "Hello";
          String name = "John Doe";

          // Concatenating strings
          String message = greeting + ", " + name + "!";

          // Getting the length of a string
          int length = message.length();

          // Accessing characters in a string
          char firstChar = message.charAt(0);
          char lastChar = message.charAt(length - 1);

          // Checking if a string contains a substring
          boolean containsHello = message.contains("Hello");
          boolean containsWorld = message.contains("World");

          // Converting a string to uppercase and lowercase
          String upperCase = message.toUpperCase();
          String lowerCase = message.toLowerCase();

          // Splitting a string into an array of substrings
          String[] words = message.split(" ");

          // Printing the results
          System.out.println("Message: " + message);
          System.out.println("Length: " + length);
          System.out.println("First character: " + firstChar);
          System.out.println("Last character: " + lastChar);
          System.out.println("Contains 'Hello': " + containsHello);
          System.out.println("Contains 'World': " + containsWorld);
          System.out.println("Uppercase: " + upperCase);
          System.out.println("Lowercase: " + lowerCase);
          System.out.println("Words: " + Arrays.toString(words));
        }
      }
    
  

In the above example, we demonstrate various operations on strings:

  • We create strings using string literals.
  • We concatenate strings using the concatenation operator (+).
  • We get the length of a string using the length() method.
  • We access individual characters in a string using the charAt() method.
  • We check if a string contains a substring using the contains() method.
  • We convert a string to uppercase and lowercase using the toUpperCase() and toLowerCase() methods.
  • We split a string into an array of substrings using the split() method.

The example code prints the results of these operations to the console, demonstrating the manipulation and access of strings in Java.

String Immutability and String Constant Pool

String Immutability

In Java, a string is immutable, which means its value cannot be changed once it is created. When you perform operations on a string such as concatenation, substring, or conversion to uppercase/lowercase, a new string object is created with the updated value, while the original string remains unchanged. This immutability has several benefits, including:

  • Thread safety: Immutable strings are safe for concurrent access by multiple threads.
  • Caching: String objects can be cached and reused since their values cannot be modified.
  • Security: Immutable strings are used in various security-sensitive operations like storing passwords or network communication, as they cannot be modified by malicious code.
  • String constant pool: The immutability of strings is closely related to the concept of the String constant pool, which we'll explain next.

String Constant Pool

The String constant pool is a special memory area in the Java heap where string literals are stored. When you create a string using a string literal, the JVM checks if the string already exists in the constant pool. If it does, the existing string instance is returned; otherwise, a new string is created and added to the pool. This mechanism helps conserve memory by avoiding the creation of duplicate string objects with the same value.

     
          String s1 = "java";
          String s2 = "java";
          String s3 = new String("java");
     
   

In above diagram total two objects are created. One in string pool and another in heap. First JVM checks for “java” string literal in pool. As it is not present in pool so an object is create and its reference is stored in s1. Now “java” string literal is already present in pool so its reference is fetched and stored in s2. Hence s1 and s2 are pointing to same object and s1 == s2 returns true. In third case we are creating string using new keyword so it is created in heap and its reference is stored in s3. Hence s1 and s3 are pointing to different objects and s1 == s3 returns false. Above example shows that string literals with same value point to same object. Strings created using new keyword point to different objects.

Creating a Custom Immutable Class in Java

In Java, an immutable class is a class whose objects cannot be modified after they are created. To create a custom immutable class, you need to follow these guidelines:

  1. Make the class final: This ensures that the class cannot be subclassed and its behavior cannot be overridden.
  2. Declare all fields private and final: Private access prevents direct modification of fields, and final ensures that the values of the fields cannot be changed after object creation.
  3. Do not provide setter methods: By omitting setter methods, you prevent the modification of object state.
  4. Avoid returning mutable objects: If your class has fields that refer to mutable objects, make sure to return defensive copies of those objects to prevent external modifications.

Example: Custom Immutable Class

    
public final class ImmutablePerson {
  private final String name;
  private final int age;

  public ImmutablePerson(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public String getName() {
    return name;
  }

  public int getAge() {
    return age;
  }
}

// Usage
ImmutablePerson person = new ImmutablePerson("John", 30);
System.out.println(person.getName()); // Output: John
System.out.println(person.getAge()); // Output: 30
    
  

In the example above, we create a custom immutable class called `ImmutablePerson`. The class has private final fields for name and age, and a constructor that initializes these fields. Getter methods are provided to access the field values.

Once an ImmutablePerson object is created, its state cannot be modified. The usage example demonstrates creating an `ImmutablePerson` instance and retrieving its name and age using the getter methods.

Differences between String, StringBuilder, and StringBuffer in Java

Feature String StringBuilder StringBuffer
Mutable No Yes Yes
Thread-safe Yes No Yes
Performance Immutable, slow for concatenation or modification Mutable, faster for concatenation or modification Mutable, slower than StringBuilder for concatenation or modification
Usage When immutability and thread-safety are required When mutable string manipulation is required in a single-threaded environment When mutable string manipulation is required in a multi-threaded environment

Example: String, StringBuilder, and StringBuffer

    
String name = "John";                      // String
StringBuilder builder = new StringBuilder(); // StringBuilder
StringBuffer buffer = new StringBuffer();    // StringBuffer

name += " Doe";                           // Creates a new String object
builder.append("John");                    // Modifies the existing StringBuilder object
buffer.append("John");                     // Modifies the existing StringBuffer object
    
  

In the example above, we declare a variable `name` of type String, `builder` of type StringBuilder, and `buffer` of type StringBuffer. When concatenating the last name, the String object creates a new String with the updated value, while the StringBuilder and StringBuffer objects modify the existing objects without creating new ones.

String is suitable when immutability and thread-safety are required. StringBuilder is more efficient for mutable string manipulation in a single-threaded environment, while StringBuffer is used in a multi-threaded environment where thread-safety is important.

Post a Comment

Previous Post Next Post