In this article series on OCA Java 8 Certification, we delve into the intricate strategies frequently employed by exam creators, particularly focusing on String, StringBuilder, and StringBuffer concepts. This segment sheds light on common exam tactics.
String Class
Difference Between == and equals()
Always keep in mind that == is used to compare references(memory address of the object), while equals() is used to compare content. Let’s illustrate this with an example.
// Creating two string objects with the same content
String str1 = new String("Hello");
String str2 = new String("Hello");
// Using == to compare references
boolean referenceComparison = (str1 == str2);
System.out.println("Using == to compare references: " + referenceComparison);
// Using equals() to compare content
boolean contentComparison = str1.equals(str2);
System.out.println("Using equals() to compare content: " + contentComparison);
When you run this code, you’ll see that the output will be:
Using == to compare references: false
Using equals() to compare content: true
Explanation
str1
andstr2
are two separate objects created with the same content, “Hello”
==
is used to compare the references ofstr1
andstr2
. Since they are two distinct objects (created using the new keyword), the result of==
will befalse
because it checks if both variables refer to the same object in memory.
equals()
is used to compare the content ofstr1
andstr2
. In this case, since the content of both strings is the same,equals()
returnstrue
because it checks if the characters in both strings are identical.
But what do you think the output would be here?
// Creating two string objects with the same content
String str1 ="Hello";
String str2 = "Hello";
// Using == to compare references
boolean referenceComparison = (str1 == str2);
System.out.println("Using == to compare references: " + referenceComparison);
// Using equals() to compare content
boolean contentComparison = str1.equals(str2);
System.out.println("Using equals() to compare content: " + contentComparison);
When you run this code, you’ll see that the output will be:
Using == to compare references: true
Using equals() to compare content: true
Let’s understand why.
In Java, when you create a String object using the new keyword, it is stored in the heap memory. Even if you create a String object with the same content, a new object will be created. However, this is not the case when you initialize a String with the same string literal (“string literal”). For optimization reasons, if Java finds String objects that are initialized with the same literal, it will make them point to the same memory area inside the string pool.
The String Pool is a special memory area where the JVM stores string literals. its purpose is to optimize memory usage and improve performance by reusing identical string literals rather than creating new instances of those strings.
String Immutability
Strings are immutable, which means that when we create a string, we can’t change its value.
You will often encounter this concept when exam creators ask you to execute code and provide the program’s output. Let’s take an example:
String s = "java";
s.concat("launchpad");
s.substring(1, 3);
s += "launchpad.com";
System.out.println(s);
When you run this code, you’ll see that the output will be:
javalaunchpad.com
This occurs because all operations on a string create another object containing the result of the operation without altering the original object. Therefore, when encountering a scenario like this, it’s crucial to carefully verify whether the result of the operation is assigned to a reference or not.
Important String methods for the exam
To excel in the OCA Java 8 exam, understanding the nuances of String methods is crucial. Here are key tricks and insights into 13 important methods of the String class:
Method | Task | Trick |
length() | Returns the length of the string | Nothing fancy, it’s a straightforward length calculation. |
indexOf() | Finds the index of a specified character or substring. | Pay attention to the different variants of the indexOf() method: indexOf(String str), indexOf(char c), indexOf(String str, int startIndex), and indexOf(String str, int startIndex). |
charAt() | Retrieves a character at the specified index. | A StringIndexOutOfBoundsException will be raised if the index doesn’t exist in the string (the maximum index allowed is string length – 1). |
substring() | Extracts a substring from beginIndex up to, but not including, endIndex . | Remember that the endIndex parameter is exclusive. Also, using substring(i, i) will return an empty string, while attempting substring(i, j) with j < i will throw an exception. |
equals() | Compares the content of two strings for equality. | Focus on content comparison, not object reference. |
equalsIgnoreCase() | Performs case-insensitive comparison between strings. | Nothing fancy! |
toLowerCase() / toUpperCase() | Converts the string to lowercase or uppercase, respectively. | Nothing fancy! |
contains() | Checks if the string contains the specified sequence. | The contains() method takes a CharSequence as a parameter, allowing it to accept String, StringBuilder, or StringBuffer objects as well.(char not allowed). |
endsWith() / startsWith() | Verifies if the string ends or starts with the given suffix or prefix. | These methods take only strings as parameters; they do not accept char sequences or individual characters. |
replace() | Replaces characters or CharSequences within the string. | This method can take two characters or two CharSequences (String, StringBuilder, StringBuffer, etc.) as parameters. |
trim() | Removes leading and trailing whitespace from the string. | nothing fancy |
toString() method of String Class
String str1 = "hamza";
String str2 = str1.toString();
sout(str1 == str2); // true
str1 and str2 both refer to the same string literal “hamza.” When you call the toString() method on a String object, it returns the same string itself (i.e., this). So, str2 will also reference the same string as str1. Therefore, the comparison str1 == str2istruebecause bothstr1andstr2` refer to the same string object.
StringBuilder class
String objects are immutable, meaning their values cannot be changed once they are created. However, StringBuilder provides a mutable alternative where string objects can be modified. By using StringBuilder, we can create a mutable string object that allows for efficient manipulation of its content without creating new objects with each modification.
equals() of StringBuilder Class
Before going through this section, try to understand the following code snippet:
StringBuilder str1 = new StringBuilder( "Hello");
StringBuilder str2 = new StringBuilder( "Hello");
// Using ==
boolean referenceComparison = (str1 == str2);
System.out.println("Using == for comparison " + referenceComparison);
// Using equals()
boolean contentComparison = str1.equals(str2);
System.out.println("Using equals() for comparison " + contentComparison);
When you run this code, you’ll see that the output will be:
Using == for comparison false
Using equals() for comparison false
You might think that the response would be ‘false true,’ but it is not, because the equals() method will try to compare the references also.
Be aware that StringBuilder doesn’t override the equals() method, and it still has the default behavior of the Object class, which is just comparing references.
To compare two StringBuilders, we can use the toString() method to transform them into simple string objects. After that, we can compare them using the equals method. Starting from Java 11, StringBuilder implements the Comparable interface, allowing us to use the compareTo() method. If the result is 0, it indicates that the StringBuilders are equal.
substring() method of StringBuilder
Almost all the methods of StringBuilder affect the original object because StringBuilder objects are mutable. However, the substring() method actually returns a string and doesn’t affect the original object.
delete() method of StringBuilder
The delete() method does not throw an exception when provided with an index that exceeds the last index of the string. Instead, it simply truncates the string up to the last valid index. For example:
StringBuilder sb = new StringBuilder("Hello, World!");
sb.delete(7, 15); // Deletes from index 7 to the end (inclusive of index 7, exclusive of index 15)
System.out.println(sb.toString()); // Output: "Hello, "
The delete(i, e) method in StringBuilder will delete characters starting from the index i up to, but not including, the index e. The ending index e is exclusive, meaning the character at index e itself will not be deleted.
Important StringBuilder methods for the exam
Method | Tasks | Tricks |
length() | Returns the length of the string | Nothing fancy, it’s a straightforward length calculation. |
capacity() | Returns the capacity of the string | Pay attention to the difference between length() and capacity() methodsCapacity refers to the total amount of space allocated by the StringBuilder/StringBuffer to hold characters, including both used and unused space. |
charAt() | Returns a character at a specific index | Same as the String class |
indexOf() | Finds the index of a character or substring | Pay attention: indexOf() in StringBuilder class has only 2 variants (takes a string as an argument) |
substring() | Extracts a substring | Same as the String class |
equals() | Checks equality | Be aware: it checks reference equality, not content equality |
append() | Appends something to the end of the string | Note: There is an append() method for almost every data type |
insert() | Inserts something at a specific position | We can insert at the length index (no exception will be raised) |
delete() | Deletes a range from the string | delete(s, e) will not raise an exception even if e extends beyond the string’s last index |
deleteCharAt() | Deletes a character at a specific index | An exception will be raised if the index is out of bounds |
toString() | Converts a StringBuilder to a String | Nothing fancy |
reverse() | Reverses the string | Nothing fancy |
StringBuilder VS. StringBuffer
StringBuilder was introduced in Java version 5 as an alternative to StringBuffer for handling string mutability. The key difference between the two lies in thread safety: StringBuffer is thread-safe, preventing multiple threads from writing to it simultaneously, whereas StringBuilder is not. In terms of performance, StringBuilder excels due to its lack of thread safety, making it the preferred choice when efficiency is paramount.
Conclusion
In this article, we’ve delved into some of the common tricks employed by OCA Java 8 exam creators, shedding light on essential concepts like string immutability, string pool, StringBuilder vs. StringBuffer, and important String/StringBuilder methods.
2 responses
Could you please add an explanation about the intern() method for String class? It would be great to cover how it interacts with the string pool.
Thanks for the suggestion! I’ve added an explanation of the intern() method to my TODO list. Stay tuned!