String in Java
In Java, strings are fundamental for handling sequences of characters. Unlike many other programming languages where strings are often treated as arrays of characters, in Java, strings are objects of the java.lang.String
class. This object-oriented approach provides a rich set of built-in features for string manipulation.
We use strings because they offer a comprehensive set of features for text manipulation. Even though they are objects, Java provides special support, allowing them to be created easily using string literals (e.g., "Hello World!"
) and concatenated with the +
operator.
A key reason for their widespread use is their immutability: once a String
object is created, its content cannot be changed. This characteristic allows for efficient memory management and enhances security. The String
class provides numerous methods for tasks like comparing content (equals(), compareTo()), finding length (length()), accessing characters (charAt()), and extracting parts (substring()).
Being part of the java.lang
package, which is automatically imported into every Java program, String
is fundamental to core Java functionalities. For scenarios requiring modifiable character sequences, Java offers StringBuffer
and StringBuilder
.
Creating Strings
There are two main methods in Java for creating String
objects:
- Using String Literals: The simplest method is to use double quote marks to surround a string of characters. Every time you use a string literal in your code, the Java compiler automatically generates a
String
object. - Using the new keyword and Constructors: Use the
new
keyword and aString
constructor to instantiate aString
object, just like you would any other object. A number of constructors are available in theString
class to initialise the strings including character arrays and otherString
objects.
String Literals vs. String Objects
Although String
objects are produced by both approaches, there is a crucial difference between them. Because strings are “interned,” Java frequently utilises the same object instance for identical string literals in order to conserve memory. However, even if the content of the new
keyword is the same as that of an existing string, it always generates a new object in memory.
This difference is critical when using the ==
operator versus the equals()
method for comparison:
==
operator: Object references (memory locations) are compared using the == operator. It only yieldstrue
if both variables point to the same memory object.- equals() method: Comparing the strings’ content (character sequence) is possible with the equals() method.
Consider this example:
String s1 = "Vengat"; // Literal string
String s2 = "Vengat"; // Literal string
String x1 = new String("vengat"); // Non-literal string
String x2 = new String("vengat"); // Non-literal string
System.out.println(s1 == s2); // Output: true (literals often share memory)
System.out.println(s1.equals(s2)); // Output: true (content is same)
System.out.println(x1 == x2); // Output: false (different objects)
System.out.println(x1.equals(x2)); // Output: true (content is same)
Output: true
true
false
true
It is possible to determine whether objects share memory by using the System.identityHashCode()
method.
String Immutability
A crucial characteristic of String
objects in Java is that they are immutable. This means that once a String object is created, its content (the sequence of characters) cannot be changed.
When you perform an action that appears to change a string (such as concatenating or changing it to uppercase), Java actually creates a new String
object with the updated sequence, leaving the old unaltered. Better security and effective implementation are made possible by this design decision.
Common String Methods
There are several ways to examine and work with string content using the String
class:
- length(): Gives back how many characters are in the string.
- charAt(int index): Gives back the character at the key. Indexes for strings begin at zero.
- indexOf(String str) / lastIndexOf(String str): Using indexOf(String str) / lastIndexOf(String str), one can find the first or last instance of a given character or substring and retrieve its index. -1 if it cannot be located.
- substring(int beginIndex) / substring(int beginIndex, int endIndex): A new string that is a substring of the original string is returned by the substring(int beginIndex) / substring(int beginIndex, int endIndex) function. An exclusive index is the
endIndex
. - equals(Object anObject) / equalsIgnoreCase(String anotherString): This function compares strings for equality regardless of case.
- compareTo(String anotherString): This function compares two strings lexicographically (using Unicode values) by using compareTo(String anotherString). if the invoking string is greater than
anotherString
, returns a positive number; if equal, returns 0. - toUpperCase() / toLowerCase(): These functions change all characters in a new
String
to uppercase or lowercase. - replace(CharSequence target, CharSequence replacement): The function
replace(CharSequence target, CharSequence replacement)
yields a newString
withreplacement
for every instance oftarget
.
Mutable Strings
Java offers StringBuffer
and StringBuilder
as two substitute classes for scenarios requiring modified character sequences because String
objects are immutable.
- StringBuffer: Thread-safe and synchronised is StringBuffer. This makes it appropriate for situations with multiple threads, but it has a performance penalty.
- StringBuilder: Quicker than
StringBuffer
, but not thread-safe (non-synchronized). For operations that are single-threaded, it is recommended.
Both classes provide comparable ways to modify:
- append(String s): Concatenating content to the end is done with append(String s).
- insert(int offset, String s): The function insert(int offset, String s) adds content at a given location.
- replace(int startIndex, int endIndex, String str): A section of the string can be replaced using the replace function (int startIndex, int endIndex, String str).
- reverse(): Reversing the character sequence is possible with reverse().
Example demonstrating mutability:
StringBuffer strB = new StringBuffer("study");
strB.append("tonight");
System.out.println(strB); // Output: studytonight
String str = "study";
str.concat("tonight");
System.out.println(str); // Output: study (original String unchanged)
Output: studytonight
study
Overview of Package
Every Java program imports the java.lang
package automatically. Classes and interfaces that are essential to practically all Java programming are included in it.
The following are important classes in java.lang
:
- Object: In Java, all classes either directly or indirectly derive from
Object
, which is the base of the class hierarchy. Basic functions likeequals()
,hashCode()
, andtoString()
are defined. - System: Offers standard input (
System.in
), standard output (System.out
), and error streams (System.err
) as well as access to system resources. - String: As mentioned, this is a representation of unchangeable character strings.
- StringBuffer and StringBuilder: Character sequences that can be changed are provided by StringBuffer and StringBuilder.
- Primitive Type Wrappers: Classes like
Integer
,Double
,Boolean
,Character
,Long
,Float
,Byte
, andShort
that encapsulate primitive data types into objects. These are helpful for conversions between types or for actions that need objects (like collections). To convert a string to an integer, for instance, useInteger.parseInt("123")
.
This package provides the fundamental building blocks for creating any application and serves as the foundation for the Java programming language.