String and StringBuilder | Preparing for Java Oracle Associate Certification (OCA) / Java basic technical tests

String and StringBuilder classes don’t work the same at all. Here are the differences between them as well as tricks that you can encounter in certification or application tests. This topic is part of the OCA (Java Oracle Certified Associate).

String

String objects are immutable, although it might not be transparent. You can use a string with a concatenation operator (+ or +=), and have the feeling that the string was modified. In fact, it was not: a new object was created! Every modification of a string creates a new object. You should be able to count the number of objects created when you see a code snippet.

Gotcha! Because the String object is immutable, “changes” to it have to be assigned to a variable. Otherwise, the changes are lost! That’s something they like very much to test in exams and certifications!

        String word = "Hello";
        word.concat(" World");
        word += "!"; // this works because += is equivalent to concatenation AND assignment!
        word.substring(0,4);
        word.replace('l','1');
        System.out.println(word); // outputs "Hello!"
        
        word = word.substring(0,4);
        word = word.replace('l','1');
        System.out.println(word); // outputs "He11"

The String class is final, as are all its methods. It means you cannot inherit it thus override its methods. Don’t confuse with the toString() method defined by the Object class!

Although a string is an array of chars, there are not casting possibilities between the two types! You cannot change one with another. Some methods are overridden in a way that allows you to use String and char parameters, but that’s basically because they are two distinct method signatures.

You have to know how concatenation works with multiple types in the expression. As soon as a String is encountered, the + sign becomes a concatenation operation for all remaining values. But while only numerics are met, it’s just an addition sign.

1 + 1 + "foo" + 1 + 1; // 2foo11
"foo" + 1 + 1 + 1 + 1; // foo1111

String pool and intern

String are reference types, which means they work as any Object type. Well, kind of… There is a mechanism called “String pool” or “interning” that allows for fewer use of memory when handling strings (a similar phenomenon exists with wrapper classes but that’ll be discussed then).

The JVM would collect all strings that contain exactly the same text at instantiation and make all references point to the same object (they might be in different classes, packages…).

But this would only work with instantiation (first assignment) and also it’s not used with the syntax = new String(“…”); (which is rarely used but you can see it in exam questions). It works for instantiated variables as well as string literals.

The method intern() returns the interned string, it creates an exact copy of the heap string object in the string constant pool (if it doesn’t exist yet).

String methods

You have to know the methods, their parameter types, return type and behavior. Also because strings are immutable, be aware that method chaining may create several strings (every method returning a String does in fact).

  • int length()
  • char charAt(int index), can throw IndexOutOfBoundsException
  • int indexOf(char ch) /(char ch, int fromIndex)/(String str)/(String str, int fromIndex), returns first match or -1 if not found
  • int lastIndexOf(same signatures as previous), returns last match or -1 if not found
  • String substring(int beginIndex)/(int beginIndex, int endIndex), as in all Java native methods returning a subset, the begin index is included and the end index is excluded; (1,1) would return an empty String and (7,2) would throw an exception
  • String to[Lower/Upper]Case(String str)
  • boolean equals(String str)/equalsIgnoreCase(String str)
  • boolean [starts/ends]With(String suffix/prefix), which is case sensitive
  • boolean contains(String str), also case sensitive
  • String replace(char old, char new)/(CharSequence old, CharSequence new), replaces all occurrences; char is single quoted ‘ ‘ and CharSequence is doubly quoted ” “; both types can’t be mixed in the parameters; CharSequence is an interface implemented by String, StringBuilder…
  • String trim()
  • String concat(string str), does the same as str1 + str2

Methods using an index may throw StringIndexOutOfBoundsException.

StringBuilder

StringBuilder is also part of the java.lang package which doesn’t need to be explicitly imported.

A StringBuilder is also represented by a char array. The big difference with String is that it’s mutable, thus requires less memory for numerous operations on strings. Changes to a StringBuilder object changes its own state and returns a reference to itself. However, StringBuilder class is also final.

To instantiate a StringBuilder you have to use the new operator. If you only assign an existing SB you make a shallow copy, thus two references pointing to the same object.

You cannot assign a String to a StringBuilder (StringBuilder sb = “foo” won’t compile).

Available constructors are

  • new StringBuilder();
  • new StringBuilder(“a string”);
  • new StringBuilder(10); = capacity (not length!), which is not final and will be dynamically expanded if needed; default capacity is 16

StringBuilder methods

  • chartAt, indexOf, length, substring are same as the String definitions. All methods like substring, subsequence, sublist… return a String and don’t change the state of the StringBuilder!
  • StringBuilder append(String str)
  • StringBuilder insert(int index, String str), where index can be at most the length (would insert at the end of the SB)
  • StringBuilder delete(int start, int end)
  • StringBuilder deleteCharAt(int index)
  • StringBuilder reverse()
  • String toString()
  • int capacity(), returns allocated capacity, which is not fixed, and is not necessarily equal to the value of length(), which is actual length

Methods using an index may throw StringIndexOutOfBoundException.

Comparing String / StringBuilder

Always good to remind:

  • string == string will compare the reference (so it would only return true if both are in the string pool), always use .equals/.equalsIgnoreCase
  • StringBuilder doesn’t override equals so references would be compared
  • String and StringBuilder cannot be compared with each other

What to study next? Subscribe to receive new posts and read previous Java certification articles.

Leave a Reply

Your email address will not be published. Required fields are marked *

Don’t miss out!

Receive every new article in your mailbox automatically.


Skip to content