Unlocking the Power of the java.lang Package: A Comprehensive Guide on String, StringBuffer and StringBuilder

Table of Contents

The java.lang package forms the core foundation of the Java programming language, encompassing fundamental classes and utilities essential for Java development. Within this package, crucial classes like String, StringBuffer, StringBuilder, and various primitive data types reside, offering robust functionalities for string manipulation, mathematical operations, and more. Understanding the nuances of these classes, including their differences, constructors, methods, and best practices, is vital for every Java developer. Moreover, delving into concepts such as immutability, synchronization, and method chaining within the java.lang package provides insights into efficient coding practices and performance optimization strategies.

java.lang package String Basic Concept in Java

In Java, strings are immutable. Once a string object is created, any attempt to modify it actually results in the creation of a new string object. This immutability means that the original object remains unchanged. Let’s dive into the distinction between immutable and mutable objects.

Consider the following snippet:

Java
String s = new String("softAai");
s.concat("Apps");
System.out.println(s); // Output: softAai
Java
s ---> softAai
       |
        ----> softAaiApps // Here, a new object will be created with those changes, but it doesn't hold any reference in this case. So, by default, it is eligible for garbage collection.

Here clearly shows that, once we create a string object, we can’t perform any changes to the existing object. If we try to perform any change, a new object will be created with those changes. This non-changeable behavior is known as the immutability of strings.

Mutable Objects: StringBuffer

Let’s examine another scenario involving a mutable object, StringBuffer:

Java
StringBuffer sb = new StringBuffer("softAai");
sb.append("Apps");
System.out.println(sb); // Output: softAaiApps
Java
sb ---> softAaiApps

Unlike strings, StringBuffer objects in Java are mutable. This means that modifications can be made directly to the existing object without creating new ones.

Here’s what happens:

Initially, sb references the StringBuffer object containing “softAai”.

Upon calling sb.append("Apps"), the content of sb is modified to “softAaiApps” in place.

As a result, when we print sb, it displays “softAaiApps”, reflecting the changes made directly to the original object.

This mutability allows for efficient manipulation of StringBuffer objects, as they can be altered without the overhead of creating new objects.

Understanding “==” Vs .equals() in Java Strings

Let’s explore the comparison between “==” and .equals() methods in Java strings:

Java
String s1 = new String("softAai");
String s2 = new String("softAai");
System.out.println(s1 == s2);      // Output: false
System.out.println(s1.equals(s2)); // Output: true
Java
//Note: This not output

s1 --> softAai
s2 --> softAai

In the String class, .equals() is overridden for content comparison. Hence, even though the objects are different, if the content is the same, .equals() returns true.

Here’s what’s happening:

Initially, s1 and s2 both reference separate String objects with the content “softAai”.

When we use “==” to compare s1 and s2, it checks whether they reference the same object in memory. Since s1 and s2 are distinct objects, the result is false.

However, when we use .equals(), it compares the content of the strings. In the case of String objects, the .equals() method is overridden to compare the content of the strings rather than their references. Since the content of s1 and s2 is the same, .equals() returns true.

This distinction is important: “==” checks for reference equality, while .equals() checks for content equality. In the context of strings, .equals() is typically used to compare their actual values.

Exploring “==” vs. .equals() in StringBuffer

By the way, what will happen in StringBuffer? 🤔

Let’s analyze the behavior of “==” and .equals() methods when used with StringBuffer objects:

Java
StringBuffer sb1 = new StringBuffer("softAai");
StringBuffer sb2 = new StringBuffer("softAai");
System.out.println(sb1 == sb2);         // Output: false
System.out.println(sb1.equals(sb2));    // Output: false
Java
sb1 --> softAai
sb2 --> softAai

In Java, “==” compares references, while .equals() typically compares content, but in the case of StringBuffer, .equals() does not compare content; instead, it defers to the default implementation of the equals() method in the Object class, which checks for reference equality.

Here’s what’s happening:

Initially, sb1 and sb2 reference separate StringBuffer objects with the content “durga”.

When we use “==” to compare sb1 and sb2, it checks whether they reference the same object in memory. Since sb1 and sb2 are distinct objects, the result is false.

Similarly, when we use .equals(), it compares the references of sb1 and sb2, not their content. Since they are distinct objects, .equals() returns false.

In StringBuffer, .equals() doesn’t override the behavior inherited from the Object class, so it performs reference comparison rather than content comparison. Thus, even though the content of sb1 and sb2 is the same, .equals() returns false because they refer to different objects in memory.

Understanding the String Constant Pool (SCP)

The String Constant Pool (SCP) in Java is a special memory area within the Java Virtual Machine (JVM) that stores unique string literals (sequence of characters enclosed in double quotation marks (")). When you create a string using double quotes (e.g., "softAai"), Java checks if a string with the same value already exists in the SCP. If it does, the existing string reference is returned; otherwise, a new string is created and added to the SCP.

Here’s how the String Constant Pool works:

Java
String Constant Pool (SCP)
--------------------------
|                        |
--------------------------

Initially, the SCP is empty. When we create a string literal "softAai", it’s added to the SCP:

Java
String Constant Pool (SCP)
--------------------------
|     "softAai"          |
--------------------------

If you create another string literal with the same value "softAai", Java will reuse the existing string from the SCP instead of creating a new one:

Java
String Constant Pool (SCP)
--------------------------
|     "softAai"          |
--------------------------

This behavior helps to conserve memory by avoiding the creation of duplicate string objects with the same value. However, it’s important to note that string objects created using the new keyword (e.g., new String("softAai")) are not added to the SCP, even if they have the same value as existing literals.

Case1: String Created Using ‘new’ Keyword

Java
String s = new String("softAai");

In this case, two objects are created: one in the heap area and the other in the SCP area. The variable s always points to the object in the heap.

Here’s the breakdown:

In the heap area, a new String object is created with the content “softAai”, and s references this object.

Java
s ==> softAai

In the SCP area, another String object with the content “softAai” is created. However, this object isn’t pointed to by any reference; it exists solely in the SCP.

Java
String Constant Pool (SCP)
--------------------------
|     "softAai"          |
-------------------------- 

// not pointing to any reference

So,

In the heap area: s points to the String object containing “softAai”. In the SCP area: There’s a String object with the content “softAai”, but it’s not referenced by any variable.

Case2: String Created Using String Literal (“”)

Java
String s = "softAai";

In this case, only one object is created in the SCP area, and s is always pointing to that object.

In the heap area, nothing is created.

In the SCP area:

Java
String Constant Pool (SCP)
--------------------------
|     "softAai"          |
--------------------------



s ==> softAai  // here 's' points to the String object containing "softAai"

A String object with the content “softAai” is created. s directly references this object.

In the heap area: No new objects are created because string literals (here “softAai”) are directly stored in the SCP. Therefore, there’s no need for a separate object in the heap.

Understanding Object Creation in SCP and Heap

Object creation in the SCP is optional. First, it will check if any object is present in SCP with the required content. If an object is already present, the existing object will be reused. If an existing object is not available, then a new object will be created. However, this rule is applicable only for SCP and not for the heap.

GC is not allowed to access the SCP area. Hence, even though an object doesn’t contain a reference variable, it is not eligible for GC if it is present in the SCP area. All SCP objects will be destroyed at the time of JVM shutdown.

Let’s explore the nuances of object creation in the String Constant Pool (SCP) and the heap, along with garbage collection considerations:

Consider the following examples:

Example 1

Java
String s1 = new String("softAai");
String s2 = new String("softAai");
String s3 = "softAai";
String s4 = "softAai"

In the heap area:

Java
s1 ==> softAai  
s2 ==> softAai

s1 and s2 refer to separate String objects with the content “softAai”.

In the SCP area:

Java
s3, s4 ==> softAai

s3 and s4 both refer to the same String object containing “softAai”

Here Total 3 objects created (2 in heap, 1 in SCP)

Note: Whenever we use the new operator, a new object will be created in the heap area. Hence, there may be existing two objects in the heap area but not in SCP. That means duplicate objects are possible in the heap area but not in SCP.

Java
String s1 = new String("softAai");
s1.concat("Apps");
String s2 = s1.concat("Blogs");
s1 = s1.concat("Jobs");

System.out.println(s1); // softAaiJobs
System.out.println(s2); // softAaiBlogs

In the heap area:

Java
s1 ==> softAai  // With the new operator, a new object will be created in the heap area and one in SCP.
     ==> softAaiApps  // Due to runtime change like .concat(), a new object will be created with those new changes.
s2 ==> softAaiBlogs
s1 ==> softAaiJobs  // As reference reassignment.
  • s1 initially refers to a String object with the content “softAai”.
  • After s1.concat("Apps"), a new object “softAaiApps” is created due to the immutable nature of strings.
  • s2 refers to a String object “softAaiBlogs” created by concatenating “softAai” with “Blogs”.
  • Finally, s1 is reassigned to a new object “softAaiJobs” after concatenating “Jobs”.

In the SCP area:

Java
==> softAai  // With the new operator, a new object will be created in the heap area and one in SCP, not holding any reference here.
==> Apps  // This is a string constant, thus created in SCP.
==> Blogs
==> Jobs

Objects “softAai”, “Apps”, “Blogs”, and “Jobs” are created due to string literals and stored in the SCP.

Total 8 objects are created (4 in heap and 4 in SCP).

Note: For every string constant, one object will be placed in the SCP area. If an object is required to be created due to some runtime operation, that object will be placed only in the heap area, not in SCP.

Understanding String Constructors

Let’s explore the various constructors available in the String class in Java:

String s = new String();
  • This constructor creates an empty string object with a size of zero.
  • Example: String s = "";
String s = new String(String literal);
  • This constructor creates a string object in the heap for the given string literal.
  • Example: String s = new String("softAai");
String s = new String(StringBuffer sb);
  • This constructor creates a string object for an equivalent StringBuffer object.
  • Example:
Java
StringBuffer sb = new StringBuffer("softAai");
String s = new String(sb);
String s = new String(char[] ch);
  • This constructor creates an equivalent string object for the given char array.
  • Example:
Java
char[] ch = {'a', 'b', 'c', 'd'};
String s = new String(ch);
System.out.println(s); // Output: abcd
String s = new String(byte[] b);
  • This constructor creates an equivalent string object for the given byte array.
  • Example:
Java
byte[] b = {100, 101, 102, 103};
String s = new String(b);
System.out.println(s); // Output: defg (as a-97, b-98, c-99, d-100, similarly for e, f, g)

Output – defg –> as ASCII Code a corresponds to 97, b corresponds to 98, c corresponds to 99, and d corresponds to 10.

Here, each constructor provides a way to create string objects from different sources such as literals, StringBuffer objects, char arrays, or byte arrays, offering flexibility in string manipulation and handling in Java.

Important Methods of the String Class

Let’s delve into some essential methods provided by the String class in Java:

public char charAt(int index);
  • This method returns the character at the specified index in the given string.
  • Example:
Java
String s = "softAai";
System.out.println(s.charAt(3)); // Output: t
// System.out.println(s.charAt(30)); // Throws StringIndexOutOfBoundsException
public String concat(String s);
  • This method concatenates the specified string to the end of the invoking string.
  • Overloaded + and += operators are also meant for string concatenation purposes only.
  • Example:
Java
String s = "softAai";
s = s.concat("Apps");
s = s + "Blogs";
s += "Jobs";
System.out.println(s); // Output: softAaiAppsBlogsJobs
public boolean equals(Object o);
  • This method performs content comparison where case is important.
  • This method is an overriding version of the equals() method in the Object class.
  • Example:
Java
String s = "amol";
System.out.println(s.equals("AMOL")); // Output: false
public boolean equalsIgnoreCase(String s);
  • This method performs content comparison where case is not important.
  • Example:
Java
String s = "amol";
System.out.println(s.equals("AMOL")); // Output: false
System.out.println(s.equalsIgnoreCase("AMOL")); // Output: true

Note: In general, we can use the equalsIgnoreCase method to validate usernames where case is not important, whereas we can use the equals method to validate passwords where case is important.

public String substring(int begin);
  • This method returns a substring starting from the specified begin index to the end of the original string.
  • Example:
Java
String s = "abcdefg";
System.out.println(s.substring(3)); // Output: defg
public String substring(int begin, int end);
  • This method returns a substring starting from the begin index to the end-1 index of the original string.
  • Example:
Java
String s = "abcdefg";
System.out.println(s.substring(2, 5)); // Output: cde
public int length();
  • This method returns the number of characters present in the string.
Java
String s = "softAai";
System.out.println(s.length()); // Output: 7

Note: The length variable is applicable for arrays but not for strings, whereas the length() method is applicable for string objects but not for arrays.

public String replace(char oldCh, char newCh);
  • This method replaces all occurrences of a specified character oldCh in the string with a new character newCh and returns the resulting string.
Java
String s = "ababa";
System.out.println(s.replace('a', 'b')); // Output: bbbbb
public String toLowerCase();
  • This method returns a new string with all characters converted to lowercase.
public String toUpperCase();
  • This method returns a new string with all characters converted to uppercase.
public String trim();
  • This method removes leading and trailing whitespace from the string, but not whitespace in the middle.
public int indexOf(char ch);
  • This method returns the index of the first occurrence of the specified character in the string.
public int lastIndexOf(char ch);
  • This method returns the index of the last occurrence of the specified character in the string.
Java
String s = "ababa";
System.out.println(s.indexOf('a')); // Output: 0
System.out.println(s.lastIndexOf('a')); // Output: 4

In this example, s.indexOf('a') returns 0 because ‘a’ first occurs at index 0 in the string “ababa”. Similarly, s.lastIndexOf('a') returns 4 because ‘a’ last occurs at index 4.

String Object Operations & Memory Allocation

Let’s see how string object operations affect memory allocation in Java:

Java
String s1 = new String("softaai");
String s2 = s1.toUpperCase();
String s3 = s1.toLowerCase();

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

Here,

In the heap area:

  • s1, s3 => softaai -> s1 and s3 both refer to the same String object with the content “softaai”.
  • s2 => SOFTAAI -> s2 refers to a new String object with the content “SOFTAAI”, as it is generated by the toUpperCase() method.

In the SCP area:

  • softaai -> Only string literal “softaai” exists

Note: Because of runtime operations, if there is a change in content, then a new object will be created in the heap. If there is no change, then the existing object will be used, and no new object will be created. Whether the object is present in the heap or SCP, the rule is the same for both.

Now, continuing with the example:

Java
String s4 = s2.toLowerCase();
String s5 = s4.toUpperCase();

In the heap area:

  • s4 => softaai -> s4 refers to a new String object with the content “softaai”, as it is generated by the toLowerCase() method./h2
  • s5 => SOFTAAI -> s5 refers to a new String object with the content “SOFTAAI”, as it is generated by the toUpperCase() method.

In short:

  • String objects in the heap are created dynamically based on operations performed on existing strings.
  • String objects in the SCP are reused if the content remains the same, but new objects are created if the content changes.

This example demonstrates how string operations can lead to the creation of new string objects in the heap, while the SCP is utilized for storing string literals and reusing existing strings when possible.

String Literal Operations & Memory Allocation

Now, Let’s understand how string literal operations impact memory allocation in Java:

Java
String s1 = "softaai";
String s2 = s1.toString();

System.out.println(s1 == s2); // Output: true

String s3 = s1.toLowerCase();
String s4 = s1.toUpperCase();
String s5 = s4.toLowerCase();

In the SCP area:

  • s1, s2, s3 => softaai -> s1, s2, and s3 all refer to the same String object with the content “softaai”.

Because of runtime operations, new objects will be created in the heap area:

In the heap area:

  • s4 => SOFTAAI -> s4 refers to a new String object with the content “SOFTAAI”, created by the toUpperCase() method.
  • s5 => softaai -> s5 refers to a new String object with the content “softaai”, created by the toLowerCase() method applied to s4.

In short:

  • String objects in the SCP are reused if their content remains the same, even when calling toString() on them.
  • However, runtime operations like toUpperCase() and toLowerCase() create new string objects in the heap, even if the content remains the same.
  • When comparing strings, using == checks for reference equality, which in this case returns true because s1 and s2 refer to the same string object.

How to Create Our Own Immutable Class

We can create our own immutable class in Java by following principles.

Once we create an object, we can’t perform any changes to that object. If we try to perform any change and there is a change in content, then a new object will be created. If there is no change in the content, then the existing object will be reused. This behavior is known as immutability.

Java
final public class Test {
    private final int i;

    public Test(int i) {
        this.i = i;
    }

    public Test modify(int i) {
        if (this.i == i) {
            return this; // If content remains the same, return existing object
        } else {
            return new Test(i); // If content changes, create a new object
        }
    }

    public int getValue() {
        return i;
    }
}


//Usage

Test t1 = new Test(10);
Test t2 = t1.modify(100);
Test t3 = t1.modify(10);

In the heap area:

  • t1, t3 => object(i=10) -> t1 and t3 reference the same object with the value 10.
  • t2 => object(i=100) -> t2 references a new object with the value 100, as it was modified.

So, once we create a Test object, we can’t perform any changes to the existing object. If we try to perform any change and there is a change in content, then a new object will be created. If there is no change in the content, then the existing object will be reused.

Final vs. Immutability

It’s important to differentiate between the concepts of final and immutability in Java:

final is applicable for variables but not for objects, whereas immutability is applicable for objects but not for variables. By declaring a reference variable as final, we won’t get any immutability nature. Even though the reference variable is final, we can perform any type of change on the corresponding objects, but we can’t perform reassignment for that variable. Hence, final and immutability are different concepts.

Let’s illustrate the difference with an example:

Java
final StringBuffer sb = new StringBuffer("softAai");
sb.append("Apps");
System.out.println(sb); // Output: softAaiApps

sb = new StringBuffer("Blogs"); // Compilation Error: cannot assign a value to final variable sb

Here,

  • We declare sb as a final variable, so we cannot reassign it to a new object after initialization. However, we can modify the state of the object it references, as StringBuffer objects are mutable.
  • Although sb is final, the StringBuffer object it references is not immutable. Therefore, appending “Apps” to the StringBuffer is allowed, but reassigning sb to a new StringBuffer object is not.

In conclusion:

  • Final variable => Valid
  • Immutable variable => Invalid
  • Final object => Invalid
  • Immutable object => Valid

StringBuffer

If content is fixed and won’t change frequently, then it is recommended to use String. If content is not fixed and keeps changing frequently, then it is not recommended to use String because for every change, a new object will be created, and in this case, performance-wise, String is not a good option. To overcome this problem, it is better to use StringBuffer. The main advantage of StringBuffer over String is that all required changes are performed on the existing object only.

Constructors

StringBuffer sb = new StringBuffer();

– Creates an empty string object with a default capacity of 16. When StringBuffer reaches its maximum capacity, then a new StringBuffer object will be created with a newCapacity = (currentCapacity + 1) * 2.

Java
StringBuffer sb = new StringBuffer();
System.out.println(sb.capacity()); // Output: 16
sb.append("abcdefghijklmnop"); 
System.out.println(sb.capacity()); // Output: 16
sb.append("q");
System.out.println(sb.capacity()); // Output: 34
StringBuffer sb = new StringBuffer(int initialCapacity);

– Creates an empty StringBuffer object with the specified initialCapacity.

StringBuffer sb = new StringBuffer(String s);

– Creates a StringBuffer object for the given String with a capacity = string.length() + 16.

Java
StringBuffer sb = new StringBuffer("softAai");
System.out.println(sb.capacity());  // Output: 21

In this example, sb is initialized with the String “softAai”, and its capacity is determined as the length of the String plus 16.

Important Methods of StringBuffer

public int length();
  • This method returns the number of characters present in the StringBuffer.
public int capacity();
  • This method returns the total capacity of the StringBuffer, i.e., how many characters it can accommodate.
public char charAt(int index);
  • This method returns the character located at the specified index in the StringBuffer.
Java
StringBuffer sb = new StringBuffer("softAai");
System.out.println(sb.charAt(3)); // Output: t
public void setCharAt(int index, char ch);
  • This method replaces the character located at the specified index with the provided character.
public StringBuffer append(…);

public StringBuffer append(int i)

public StringBuffer append(long l)

public StringBuffer append(char ch)

public StringBuffer append(boolean b)

  • Here, all above methods are overloaded.

  • These overloaded methods append various data types or strings to the end of the StringBuffer.
Java
StringBuffer sb = new StringBuffer();
sb.append("PI Value is : ");
sb.append(3.14);
sb.append(" It is exactly : ");
sb.append(true);
System.out.println(sb); // Output: PI Value is : 3.14 It is exactly : true
public StringBuffer insert(int index, ...);

public StringBuffer insert(int index, String s)

public StringBuffer insert(int index, int i)

public StringBuffer insert(int index, double d)

public StringBuffer insert(int index, char ch)

public StringBuffer insert(int index, boolean b)

Here, all methods are overloaded. In the append method, characters are added at the end, whereas in the insert method, characters are added at the specified index.

  • These overloaded methods insert various data types or strings at the specified index in the StringBuffer.
Java
StringBuffer sb = new StringBuffer("abcdefgh");
sb.insert(2, "xyz");
System.out.println(sb); // Output: abxyzcdefgh
public StringBuffer delete(int begin, int end);
  • This method deletes characters from the begin index to the end-1 index in the StringBuffer.
public StringBuffer deleteCharAt(int index);
  • This method deletes the character located at the specified index in the StringBuffer.
public StringBuffer reverse();
  • This method reverses the characters in the StringBuffer.
Java
StringBuffer sb = new StringBuffer("softAai");
System.out.println(sb.reverse()); // Output: iaaftos
public void setLength(int length);
  • This method sets the length of the StringBuffer to the specified length.
Java
StringBuffer sb = new StringBuffer("aiswaryaabhi");
sb.setLength(8);
System.out.println(sb); // Output: aiswarya
public void ensureCapacity(int capacity);
  • This method increases the capacity of the StringBuffer based on the provided capacity.
Java
StringBuffer sb = new StringBuffer();
System.out.println(sb.capacity()); // Output: 16
sb.ensureCapacity(1000);
System.out.println(sb.capacity()); // Output: 1000
public void trimToSize();
  • This method deallocates extra allocated memory to trim the StringBuffer’s capacity to its current size.
Java
StringBuffer sb = new StringBuffer(1000);
sb.append("abc");
sb.trimToSize();
System.out.println(sb.capacity()); // Output: 3

StringBuilder

Every method present in StringBuffer is synchronized, hence only one thread is allowed to operate on a StringBuffer object at a time, which may cause performance problems. To handle this issue, the concept of StringBuilder was introduced in version 1.5.

StringBuffer vs StringBuilder

StringBuilder

  • Non-Synchronized: Unlike StringBuffer, StringBuilder methods are not synchronized, allowing multiple threads to operate simultaneously on StringBuilder objects.
  • Not Thread-Safe: Because of its non-synchronized nature, StringBuilder is not inherently thread-safe.
  • Lower Thread Waiting Time: The absence of synchronization leads to lower thread waiting time, enhancing performance.
  • Introduced in Java 1.5: StringBuilder was introduced in Java version 1.5.

StringBuffer

  • Synchronized: StringBuffer methods are synchronized, meaning only one thread is allowed to operate on a StringBuffer object at a time, ensuring thread safety.
  • Thread-Safe: Due to its synchronized nature, StringBuffer is thread-safe.
  • Higher Thread Waiting Time: Synchronization can lead to higher thread waiting time, potentially impacting performance.
  • Introduced in Java 1.0: StringBuffer has been present since the initial release of Java.

It’s essential to note that everything, including methods and constructors, is the same in StringBuffer and StringBuilder, except for the synchronization aspect. StringBuffer has synchronized methods, while StringBuilder does not. This distinction provides developers with options based on their specific requirements: StringBuffer for thread-safe operations and StringBuilder for improved performance in scenarios where thread safety is not a concern.

String vs StringBuffer vs StringBuilder

  • If the content is fixed and won’t change frequently, then we use the String concept.
  • If the content is not fixed and keeps changing frequently, and we need thread safety, then we use the StringBuffer concept.
  • If the content is not fixed and keeps changing frequently, and we don’t need thread safety, then we use the StringBuilder concept.

Method Chaining

Method chaining allows consecutive method calls on an object, where each method call returns the object itself or another object of the same type, enabling a fluent and concise style of coding. This concept is widely used in classes like String, StringBuffer, and StringBuilder, where many methods return the same type as the object. call another method, which forms method chaining. In method chaining, all method calls are executed from left to right.

Java
StringBuilder sb = new StringBuilder();
sb.append("softAai").append("Apps").append("Blogs").insert(2,"xyz").reverse().delete(2,10);
System.out.println(sb);  //OUTPUT - sgolBsppAiaAtfzyxos
  • Initially, we create a StringBuilder object sb.
  • We then chain multiple methods together:
    • append("softAai"): The StringBuilder now contains “softAai”.
    • append("Apps"): “Apps” is appended to the StringBuilder, resulting in “softAaiApps”.
    • append("Blogs"): “Blogs” is appended, resulting in “softAaiAppsBlogs”.
    • insert(2,"xyz"): “xyz” is inserted at index 2, resulting in “soxyzftAaiAppsBlogs”.
    • reverse(): The content of the StringBuilder is reversed, resulting in “sgolBsppAiaAtfzyxos”.
    • delete(2,10): Characters from index 2 to index 9 (10 is exclusive) are deleted, resulting in “sgaAtfzyxos”.
  • Finally, this resulting content is printed.

Conclusion

In conclusion, the java.lang package serves as the cornerstone of Java programming, housing indispensable classes and utilities pivotal for everyday development tasks. Mastery of classes like String, StringBuffer, and StringBuilder, coupled with a deep understanding of immutability, synchronization, and method chaining, empowers developers to write efficient, concise, and robust Java code. By leveraging the capabilities offered by the java.lang package and adhering to best practices outlined herein, developers can enhance their productivity, optimize application performance, and craft software solutions that stand the test of time.

Skill Up: Software & AI Updates!

Receive our latest insights and updates directly to your inbox

Related Posts

error: Content is protected !!