03 Operators and Expressions
Basic String Operations in Java
Working with Strings
In Java, strings are objects that represent a sequence of characters.
The String class in Java provides various methods to create, manipulate,
and modify strings.
Creating Strings: We can create a string in two main ways:
String Literal: String str = "Hello";
String Object: String str = new String("Hello");
When using string literals, Java optimizes memory usage by storing
string literals in a special memory pool known as the string pool. If a
string with the same value already exists in the pool, it is reused instead
of creating a new one.
Concatenating Strings:
We can concatenate strings using the + operator:
String greeting = "Hello";
String name = "World";
String message = greeting + " " + name;
// Output: "Hello World"
// Case 1: String result = num + text;
// num is converted to a String and then concatenated
// Case 2 : 3 + 4 + "hello " = 7hello
Manipulating Strings:
concat() method: Another way to concatenate strings.
String str1 = "Hello";
String str2 = "World";
String result = [Link](" ").concat(str2);
// Output: "Hello World"
StringBuilder and StringBuffer (more on this later) are used for efficient
string manipulation when frequent modifications are needed.
2. String Storage in Memory : In Java, strings are stored in a special
memory area called the string pool (or string literal pool). This is a part
of the heap memory used for storing string constants.
String Pool (Interned Strings): When we create a string using a literal
(e.g., String s = "abc";), Java checks if this string already exists in the pool.
If it does, the reference to the existing string is returned. This avoids
creating duplicate objects in memory.
1
Heap Memory: When we create a string object using the new keyword
(e.g., new String("abc");), Java creates a new string object in the heap
memory, even if an identical string already exists in the pool.
Example:
String s1 = "abc"; // Stored in the string pool
// Stored in the heap, not the string pool
String s2 = new String("abc");
Immutability of Strings : Strings in Java are immutable, meaning that
once a string object is created, it cannot be modified. Every time you
perform a modification on a string (like concatenating or replacing
characters), a new string object is created, leaving the original string
unchanged.
Why are Strings Immutable?
Security: Immutable objects are thread-safe and ensure that their data
cannot be changed once created. This is important for classes like String,
which is used in many parts of the Java platform.
Performance: String interning (reusing string literals) only works
because strings are immutable.
Caching: Immutable strings can be cached and reused, improving
memory efficiency.
Example of Immutability:
String str = "Hello";
str = [Link](" World");
// Creates a new string object, original "Hello" is unchanged
String Comparison in Java
String Literal vs String Object
String Literal: Strings created using literals are stored in the string
pool. If the same literal exists, Java will reuse it.
String s1 = "Hello";
String s2 = "Hello";
String Object: Strings created using new are stored in the heap memory.
These strings are not automatically pooled.
String s1 = new String("Hello");
String s2 = new String("Hello");
Key Difference: The string literals are compared by reference (==), and
the objects created with new are always compared by value (i.e., their
contents).
Comparing Strings: == vs .equals()
2
== Operator: The == operator compares references (memory locations)
of two strings, not their actual content.
Use == only when checking if two variables refer to the same string
object.
.equals() Method: The .equals() method compares the content
(characters) of two strings. This is the most reliable way to compare
strings.
Example:
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
[Link](s1 == s2); // true (same reference in the pool)
[Link](s1 == s3); // false (different objects)
[Link]([Link](s3)); // true (same content)
Useful String Methods
Here are some commonly used methods in the String class:
StringBuilder and StringBuffer
StringBuilder:
Mutable: Unlike String, StringBuilder is mutable, meaning you can
modify its content without creating new objects.
Performance: Best suited for string manipulations like append, delete,
or replace where strings are frequently modified.
Thread Safety: StringBuilder is not synchronized, which means it's not
thread-safe. It performs better in single-threaded applications.
Example:
StringBuilder sb = new StringBuilder("Hello");
[Link](" World");
[Link](sb); // "Hello World"
StringBuffer:
Similar to StringBuilder, but it is synchronized (thread-safe), making it
slower in performance compared to StringBuilder. It should be used in
multi-threaded applications where multiple threads are modifying the
string at the same time.
Example:
StringBuffer sb = new StringBuffer("Hello");
[Link](" World");
[Link](sb); // "Hello World"
Key Difference Between StringBuilder and StringBuffer:
3
Thread Safety: StringBuffer is thread-safe (slower) while StringBuilder is
not thread-safe (faster).
Use Case: Use StringBuilder when thread safety is not required, and use
StringBuffer when working with threads.
Overriding toString() Method : In Java, every class inherits the toString()
method from the Object class. This method is used to return a string
representation of an object. By default, toString() returns the class name
followed by the "@" symbol and the object's hashcode (e.g.,
[Link]@15db9742).
Why Override toString()?
Overriding toString() provides a meaningful string representation of
your object, which is useful for debugging and logging.
Example:
class Person {
String name;
int age;
Person(String name, int age) {
[Link] = name;
[Link] = age;
}
// Overriding toString() to return a custom string representation
@Override
public String toString() {
return "Person[name=" + name + ", age=" + age + "]";
}
}
public class strTest4 {
public static void main(String[] args) {
Person person = new Person("Alice", 30);
[Link](person); // Output: Person[name=Alice, age=30]
}
}
Note : Use StringBuilder and StringBuffer for efficient string
manipulation in cases where frequent modifications are required.
StringBuilder is preferred unless thread safety is needed.