Java Strings API - mariamaged/Java-Android-Kotlin GitHub Wiki
Java - Strings
4.1.1 Creating String Objects
You can create
objects
of theclass
String by:
- Using the
new
operator.- Using String
literal values
(values within double quotes).
- Let' create two String objects with the value "Paul" using the operator "new":
String st1 = new String("Paul");
String str2 = new String("Paul");
System.out.println(str1 == str2);
- Comparing the objects referred to by the variables str1 and str2 prints
false
. - The operator == compares the
addresses
of theobjects
referred to by the variablesstr1
andstr2
. - Even thought these String objects store the same sequence of characters, they refer to
separate objects
stored atseparate locations
.
- Let's initialize two String variables with the value "Harry" using the assignment operator (=):
String str3 = "Harry";
String str4 = "Harry";
System.out.println(str3 == str4);
- In the case of the variables
str3
andstr4
, the objects are created and stored in a pool of String objects. - Before creating a
new object
in the pool, Java searches for an object withsimilar contents
. - When the following line executes, no String object with the value of "Harry" is found in the pool of String objects:
String str3 = "Harry";
- As a result, Java creates a String object with the value "Harry" in the pool of String objects referred to by the variable
str3
.
- When the following line of code executes, Java is able to find a String object with the value "Harry" in the pool of String objects:
String str4 = "Harry";
- Java does not create a new String object in this case, and the variable
str4
refers to the existing String object "Harry".
- You can create a String object by enclosing a value within double quotes ("):
System.out.println("Morning");
- These values are reused from the String constant pool if a
matching value
is found. - If a matching value is not found, the JVM creates a String object with the specified value and places it in the String constant pool.
String morning1 = "Morning";
System.out.println("Morning" == morning1); // Prints true.
- You can also
invoke
other overloaded constructors of the classString
to create its objects by using the operatornew
:
String girl = new String("Shreya"); // Constructor that takes a string.
char[] name = {'P', 'a', 'u', 'l');
String boy = new String(name); // Constructor that takes a char array.
- You can also create objects of String using the classes StringBuilder and StringBuffer.
StringBuilder sd1 = new StringBuilder("String Builder");
String str5 = new String(sdl);
StringBuffer sd2 = new StringBuffer("String Buffer");
String str6 = new String(sd2);
Note: Because String is a class, you can assign null to it.
The default value for String is null.
4.1.2 The class String is immutable
- Once created, the contents of an object of the class String
can never be modified
. - The immutability of String objects helps the JVM reuse String objects,:
- Reducing memory overhead.
- Increasing performance.
- String objects can be shared across multiple reference variables without any
fear of changes in their values
. - If the reference variables
str
andstr2
refer to the same String object value "Java",str1
need not worry for its lifetime that the value "Java" might be changed through the variablestr2
.
Implementation of String Immutability
- The class String stores its values in a
private
variable of the type char arraychar[] value
.- Arrays are fixed in size and don't grow once initialized.
- This value variable is marked as
final
in the class String.- Note that final is a
nonaccess modifier
, and a final variable can be initialized once.
- Note that final is a
- Non of the methods defined in the class String manipulate the individual elements of the array value.
- The char array used by the class String is marked as private, which means that that is isn't accessible
outside the class for modification
. - The class String itself doesn't modify the value of the variable either.
- All the methods defined in the class
String
, such assubstring
,concat
,toLowerCase
,toUpperCase
,trim
, and so on, which seem to modify the content of the String object on which they're called, create and return a new String object rather than modify the existing value.
4.1.3 Methods of the class String
charAt()
You can use the method charAt(int index) to retrieve a character at a specified index of a String:
String name = new String("Paul");
System.out.println(name.charAt(0)); // Prints P.
System.out.println(name.charAt(2)); // Prints a.
- Because the last character is placed at index 3, the following code will
throw an exception
atruntime
:
System.out.println(name.charAt(4));
- Runtime exception: is a
programming error
determined by the Java Runtime Environment (JRE) during the execution of the code.
indexOf()
You can search a String for the occurrence of a
char
or aString
. If the specified char or String is found in the target String, this method returns thefirst matching position
; otherwise, it returns-1
.
By default, the indexOf() methods starts its search from the
first char
of the target String.
If you wish, you can also set the
starting position
.
String letters = "ABCAB";
System.out.println(letters.indexOf('B')); // Prints 1.
System.out.println(letters.indexOf("S")); // Prints -1.
System.out.println(letters.indexOf("CA")); // Prints 2.
System.out.println(letters.indexOf("B", 2)); // Prints 4.
substring()
- The first returns a substring of a String from the
position you specify
to theend
of the String, as in the following example:
String exam = "Oracle";
String sub = exam.substring(2);
System.out.println(sub); // Prints acle.
- You can also specify the end position with this method:
String exam = "Oracle";
String result = exam.substring(2, 4);
System.out.println(result); // Prints ac.
- Here's a simple way to remember this rule:
- Length of
String
returned by substring() = end - start.
- Length of
trim()
The trim() method returns a new String by removing all the leading and trailing white space in a String.
White spaces are
blanks
(new lines, space, or tabs).
String varWithSpaces = " AB CB ";
System.out.print(":");
System.out.print(varWithSpaces);
System.out.println(":");
// : AB CB :
System.out.print(":");
System.out.print(varWithSpaces.trim());
System.out.print(":");
// :AB CB:
replace()
This method will return a new String by replacing all occurrences of a char with another char.
Instead of a char to be replaced by another char, you can also specify a sequence of characters - a String to be replaced by another String.
String letters = "ABCAB";
System.out.println(letters.replace('B', 'b')); // Prints AbCAb
System.out.println(letters.replace("CA", "12")); // Prints AB12AB
- Notice the type of the method parameters passed on this method: either
char
orString
.- You can't miss these parameter types.
String letters = "ABCAB";
System.out.println(letters.replace('B', "b")); // Won't compile.
System.out.println(letters.replace("B", 'b')); // Won't compile.
length()
You can use the length() method to retrieve the length of a String.
System.out.println("Shreya".length()); // Prints 6.
startsWith() and endsWith()
The method startsWith() determines whether a String starts with a
specified prefix
, specified as aString
.
You can also specify whether you wish to search from the start of a String or from a particular position.
This method returns true if a match is found or false otherwise.
String letters = "ABCAB";
System.out.println(letters.startsWith("AB")); // Prints true.
System.out.println(letters.startsWith("a")); // Prints false.
System.out.println(letters.startsWith("A", 3)); // Prints true.
The method endsWith() tests whether a String ends with a particular suffix.
It returns true for a matching value and false otherwise.
System.out.println(letters.endsWith("CAB")); // Prints true.
System.out.println(letters.endsWith("B")); // Prints true.
System.out.println(letters.endsWith("b")); // Prints false.
Method Chaining
It is a common practice to use multiple String methods in a single line of code:
String result = "Sunday ".replace(' ', 'Z').trim().concat("M n");
System.out.println(result); // Prints SundayZZM N
- These methods are evaluated from
left to right
.
4.1.4 String objects and Operators
- Concatenation operators (+ and +=) have a special meaning for
String
s. - Behind the scenes, string concatenation is implemented by using the StringBuilder or StringBuffer classes.
- But remember that a string is immutable.
String aString = "OCJA" + "Cert" + "Exam"; // String that contains OCJACertExam.
int num = 10;
int val = 12;
String aStr = "OCJA";
String anotherStr = num + val + aStr;
System.out.println(anotherStr); // Prints 22OCJA not 1012OCJA.
- The expression (num + val + aStr) is evaluated from left to right.
- Here's the sequence of steps executed by Java to execute the expression:
- Add operands num and val to get 22.
- Concatenate 22 with OCJA to get 220CJA.
- If you wish to treat the numbers stored in variables num and val as String values, modify the expression as follows:
String anotherStr = "" + num + val + aStr; // Evaluates to 10120CJA.
- When you use += to concatenate String values, ensure that the variable you are using has been initialized (and does not contain null).
String lang = "Java";
lang += " is everywhere";
String initializedToNull = null;
initializedToNull += "Java";
System.out.println(initializedToNull); // Prints nullJava.
4.1.5 Determining Equality of Strings
- The correct way to compare two String values for equality is to use the
equals()
method defined in the String class. - This method returns a
true
value if the object being compared to:- Is not null.
- Is a String object.
- Represents the same sequence of characters as the object to which it is being compared.
Equals Method
public boolean equals(Object anObject) {
if(this == anObject) return true;
if(anObject instanceOf String) {
String anotherString = (String) anObject;
int n = count;
if(n == anotherString.count) {
char[] v1 = value;
char[] v2 = anotherString.value;
int i = offset;
int j = anotherString.offset;
while(n-- != 0) {
if(v1[i++] != v2[j++]) return false;
}
return true;
}
}
return false;
}
4.2 Mutable Strings: StringBuilder
The class StringBuilder is defined in the package
java.lang
, and it has amutable
sequence of characters.
- You should use the class StringBuilder when:
- You're dealing with larger strings.
- You're modifying the contents of a string often.
- Doing so will improve the
performance of your code
. - Unlike StringBuilder, the String class has an immutable sequence of characters.
- Every time you modify a string that's represented by the String class, your code creates new String objects instead of modifying the existing one.
4.2.1 The StringBuilder class is mutable
- In contrast to the class
String
, the classStringBuilder
uses a non-final char array to store its value. - Following is a partial definition of the class
AbstractStringBuilder
(the superclass of the classStringBuilder
). - It includes the declaration of the variables:
value
which is used to store the value of the string.count
which is used to store the length of the string.
4.2.2 Creating StringBuilder objects
- You can create objects of the class StringBuilder using multiple overloaded constructors, as follows:
class CreateStringBuilderObjects {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder(sb1);
StringBuilder sb3 = new StringBuilder(50); // Constructor that accepts an int value specifying initial capacity of StringBuilder object.
StringBuilder sb4 = new StringBuilder("Shreya Gupta"); // Constructor that accepts a String.
}
}
- When you create a StringBuilder object using its
default constructor
, the following code executes behind the scenes to initialize the arrayvalue
defined in the StringBuilder itself.
public StringBuilder() {
this.value = new char[16];
}
- When you create a StringBuilder by passing it a String, the following code executes behind the scenes to initialize the array value:
public StringBuilder(String str) {
this.value = new char[str.length() + 16];
this.append(str);
}
- When you create a StringBuilder by passing it an integer:
public StringBuilder(int x) {
this.value = new char[x];
}
4.2.3 Methods of class StringBuilder
append()
The append method add the specified value at the
end
of the existing value of a StringBuilder object.
- Because you may want to add data from
multiple data types
to a StringBuilder object, this method has been overloaded so that it can accept data of any type.
- This method accepts
all the primitives
,String
,char array
, andObject
, as method parameters, as shown in the following example:
class AppendStringBuilder {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder();
sb1.append(true); // Appends boolean.
sb1.append(10); // Appends int.
sb1.append('a'); // Appends char.
sb1.append(20.99); // Appends double.
sb1.append("Hi"); // Appends String.
System.out.println(sb1); // Prints true10a20.99Hi.
}
}
- You can append a complete
char array
,StringBuilder
, orString
or its subset as follows:
StringBuilder sb1 = new StringBuidler();
char[] name = {'J', 'a', 'v', 'a', '8'};
sb1.append(name, 1, 3); // Starting with position 1 append 3 characters, position 1 inclusive.
System.out.println(sb1); // Prints ava.
- Because the method append also accepts a method parameter of type
Object
, you can pass it any object from theJava API
or yourown user-defined object
:
class AppendStringBuilder2 {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder();
sb1.append("Java");
sb1.append(new Person("Oracle")); // Append object of class Person.
System.out.println(sb1);
}
}
class Person {
String name;
Person(String str) {this.name = str;}
}
- The output of the previous code is:
- When you append an object's value to a StringBuilder, the method append calls the static String.valueOf() method.
- The version taking an
Object
parameter:- Returns the four-letter string "null" if the parameter is null.
- Otherwise, it calls its
toString()
method. - If the
toString()
method has been overriden by the class, then the method append adds the String value returned by it to the target StringBuilder object. - In the absence of the overriden
toString
method, thetoString()
in the class Object executes.- For your information, the
default implementation
of the method toString() in the class Object:- Returns the name of the class.
- Followed by the
@char
. - And
unsigned hexadecimal representation
of thehashcode
of the object (the value returned by the object's hashCode() method).
- For your information, the
append implementation
public AbstractStringBuilder append(boolean b) {
if(b) {
int newCount = count + 4;
if(newCount > value.length) expandCapacity(newCount);
value[count++] = 't';
value[count++] = 'r';
value[count++] = 'u';
value[count++] = 'e';
}
else {
int newCount = count + 4;
if(newCount > value.length) expandCapacity(newCount);
value[count++] = 'f';
value[count++] = 'a';
value[count++] = 'l';
value[count++] = 's';
value[count++] = 'e';
}
}
Insert
- The insert method is as powerful as the append method.
- It also exists in multiple flavors (read: overloaded method) that accept any data type.
- The main difference between the
append
andinsert
methods is that:- The insert method enables you to insert the requested data at a
particular position
. - The append method allows you add the requested data only at the
end
of the StringBuilder object.
- The insert method enables you to insert the requested data at a
class InsertStringBuilder {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder("Bon");
sb1.insert(2, 'r');
System.out.println(sb1); // Prints Born.
}
}
- You can also insert a complete
char array
,StringBuffer
,orString
or its subset, as follows:
StringBuilder sb1 = new StringBuilder("123");
char[] name = {'J', 'a', 'v', 'a'};
sb1.insert(1, name, 1, 3);
System.out.println(sb1); // Prints 1ava23.
delete() and deleteCharAt()
The method delete removes the characters in a substring of the specified StringBuilder.
The method deleteCharAt removes the char at the specified position.
class DeleteStringBuilder {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder("0123456");
sb1.delete(2, 4);
System.out.println(sb1); // Prints 01456.
}
}
class DeleteStringBuilder {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder("0123456");
sb1.deleteCharAt(2);
System.out.println(sb1); // Prints 013456.
}
}
trim()
Unlike the class String, the class StringBuilder doesn't define the method
trim()
.
An attempt to use it with this class will
prevent
your code fromcompiling
.
reverse()
As the name suggests, the reverse method reverses the sequence of characters of a StringBuilder.
- You can't use the method
reverse
to reverse asubstring
of StringBuilder.
class ReverseStringBuilder {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder("0123456");
sb1.reverse();
System.out.println(sb1); // Prints 6543210.
}
}
replace()
Unlike the replace method defined in the class String, the replace method in the class StringBuilder replaces a
sequence of characters
, identified by theirpositions
, with anotherString
, as in the following example:
class ReplaceStringBuilder {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder("0123456");
sb1.replace(2, 4, "ABCD");
System.out.println(sb1); // Prints 01ABCD456.
}
}
subSequence()
Apart from the method
substring
, you can also use the method subSequence to retrieve a sequence of a StringBuilder object.
- This method returns objects of type
CharSequence
. - This method
does not modify
the existing value of a StringBuilder.
class SubSequenceStringBuilder {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder("0123456");
System.out.println(sb1.subSequence(2, 4)); // Prints 23.
System.out.println(sb1); // Prints 0123456.
}
}
A quick note on StringBuffer
- The classes StringBuffer and StringBuilder offer the
same functionality
, with one difference:- The
methods
of the class StringBuffer aresynchronized
where necessary, whereas the methods of the class StringBuilder aren't.
- The
- When you work with the class StringBuffer,
only one thread
out of multiple threads can execute your method. - This arrangement prevents any
inconsistencies
in the value of the instance variables that are modified by these (synchronized) methods. - But it introduces
additional overhead
, so working with synchronized methods and the StringBufferaffects the performance
of your code.