The String ClassS2C Home « The String Class

In our first lesson of this section we learn all about the predefined String object. We look at string immutability, creation and efficiency before finishing the lesson by looking at some of the methods available for use with this class.

From the very first program we wrote on the site we have been using the String object as it is part of the main() method we used in that program. Up until now we have used the String object quite happily, without knowing much about the String object or its many methods. We have even been creating String objects without realizing it; everytime we have created a string literal for output to the console, behind the scenes Java has been converting the literal to a String object.

Strings and their usage are such a fundamental part of any programming language that getting used to using strings is well worth the inital effort. So in this lesson we will make a thorough investigation of the String object and look at several of the methods available for use with strings.

Before we get started, we should mention a couple of things about strings in Java:

  • Most computer languages use the standard 8-bit ASCII character set which has a range of 0 to 127 to represent the characters of a string. Java uses Unicode, which defines a character set, that can represent any character found in any human language and has a range of 0 to 65,536. The ASCII character set is a subset of Unicode and as such ASCII characters are still valid in Java.
  • In Java a String object is immutable, that is to say that once a String object has been constructed its contents can never be changed.

Creating A Folder For Our API Contents Source Files

As this is a new section we will create a folder for our API Contents files, in Windows this would be:

double click My Computer icon

double click C:\ drive (or whatever your local drive is)

right click the mouse in the window

from the drop down menu Select New

click the Folder option and call the folder _APIContents and press enter.

String ImmutabilityTop

If you change the contents of a String object, you are in effect creating a new String object. This might seem a bad idea until you realize that making String objects immutable is done for efficiency reasons. String objects are constant because of their immutability and as such String objects can be shared. This is done by checking the contents of new String objects against an area of heap memory known as the String constant pool. If a string already exists in this pool that is the same as the new String object then the String objects reference variable is just pointed to this area of The Heap, thus saving space. Lets take a closer look at what immutability means with a slide show; just press the button below to step through each slide.

heap 11 heap 12 heap 13 heap 14

Press the button below to cycle through our String Immutability explanation.


Lets look at some code to illustrate the above scenario and prove that the str1 and str2 reference variables point to the same object, so that we can see the reuse of strings in the string constant pool:


/*
  String immutability and the String Constant Pool
*/
import static java.lang.Math.acos;
 
public class TestString {
    public static void main(String[] args) {
        String str1 = "java";
        System.out.println("str1 = " + str1);
        str1 = "tutor";
        System.out.println("str1 = " + str1);
        str1 = "javatutor";
	String str2 = "javatutor";
        System.out.println("str1 = " + str1);
        System.out.println("str2 = " + str2);
        System.out.println(str1 == str2);
    }
}

Save, compile and run the file in directory   c:\_APIContents in the usual way.

string test

The output of true at the end is the part of the output we are most interested in. We know from previous discussion of Checking Object Equality that when we use == relational operator to test object equality, the result is only ever true when both operands refer to the same object. So this test proves reuse of the "javatutor" string by returning true.

String Creation & EfficiencyTop

We spoke above of how String objects we create are placed within their own area of The Heap known as the String constant pool. This isn't the fully story though. All the String objects we created above were created from string literals, without any mention of the new operator. The String object has many different constructors and using them can impact on the objects we create and their effieciency. Following is a snapshot of a few of the ways we can a instantiate String object:


String str2 = new String("javatutor");
String str1 = "java";
String str3 = new String(str2);

What isn't apparent about the instantiation methods above is the different impacts they have on object creation and thus efficiency. Lets take a closer look at how String object instantiation affects efficiency with a slide show; just press the button below to step through each slide.

heap 15 heap 16 heap 17 heap 14

In this slide we are actually creating 2 String objects. The first is created on The Heap and reference str1 refers to this String object. The JVM then creates a second String object within the String constant pool as there is no match for the value "java" within the pool.

In this slide we don't create any String objects as an object exists within the String constant pool with the value "java" so reference str2 refers to this.

In this slide although we are using the new operator we are just creating 1 String object on The Heap and reference str3 refers to this String object. We use the value "java" from reference str2 to do this. We don't create any other String objects as an object already exists within the String constant pool with the value "java".

In this slide we don't create any String objects as an object exists within the String constant pool with the value "java" so reference str4 refers to this. So at the end we have only created three objects showing how the JVM reuses objects for efficiency via the String constant pool

Press the button below to cycle through our String Creation & Efficiency explanation.


Lets look at some code to illustrate the above scenario and prove that different String objects are created, both on The Heap and in the string constant pool:


/*
  String creation and efficiency
*/
public class TestString2 {
    public static void main(String[] args) {
        String str1 = new String("java");
	String str2 = "java";
        String str3 = new String(str2);
	String str4 = "java";
        System.out.println("str1 = " + str1);
        System.out.println("str2 = " + str2);
        System.out.println("str3 = " + str3);
        System.out.println("str4 = " + str4);
        System.out.println(str1 == str2); // test 1
        System.out.println(str1 == str3); // test 2
        System.out.println(str1 == str4); // test 3
        System.out.println(str2 == str3); // test 4
        System.out.println(str2 == str4); // test 5
        System.out.println(str3 == str4); // test 6
    }
}

Save, compile and run the file in directory   c:\_APIContents in the usual way.

string test2

The screenshot above shows the string values held by reference variables str1, str2, str3 and str4; the values are all equal. As mentioned above we know from previous discussion of Checking Object Equality that when we use == relational operator to test object equality, the result is only ever true when both operands refer to the same object. So what we then do is test all four references to see if any are actually referring to the same object. It transpires that only test 5 returns true which tests str2 against str4. This makes sense as these reference variables refer to the same object within the String constant pool as shown in the slideshow above. The other two objects were created on The Heap and so the reference variables refer to different objects.

String Methods OverviewTop

The table below shows the declarations of the methods in the String class we cover in this lesson:

Method Declaration Description
Discussed in this lesson
public char charAt(int index)Return the character at the specified index position of the invoking string.
public String concat(String str)Returns a String object of the invoking string value appended with the argument string value.
public boolean equals(String str)Returns true if the invoking string has the the same character sequence as the argument string.
public int length()Returns the length of the invoking string.
public String replace(char old, char new)Returns a String object of the invoking string value where any occurrences of the first argument char value are replaced with occurrences of the second argument char value.
public String toString()Returns a string description of the object.

We will go through the above String methods in this lesson. Use the link below for more information on the other String methods, and there are a lot, available in the String class that are not covered here.

Java DocumentationTop

As mentioned in the first four sections Java comes with very rich documentation. The following link will take you to the online version of documentation for the JavaTM 2 Platform Standard Edition 5.0 API Specification. Take a look at the documentation for the String class which you can find by scrolling down the upper left pane and clicking on java.lang, then go to the lower left pane and click on String. You will go back to this documentation time and time again so if you haven't done so already I suggest adding this link to your browser's favourites toolbar for fast access.

The charAt() MethodTop

The charAt() method will return the character at the specified index position of the invoking string. The following code and screenshot shows examples of using the String class charAt() method:


/*
  The charAt() method
*/
public class TestCharAt {
    public static void main(String[] args) {
        String str1 = new String("java");
        System.out.println(str1.charAt(3));
        System.out.println(str1.charAt(5));
    }
}

test charAt() method

As you can see from the screenshot the class printed a to the console. Indexes in java are zero-based, so the outpur is correct. The program then abended with a StringIndexOutOfBoundsException exception. This is because the index only goes to 4 (zero based remember) and we looked for a character at index 5. So be aware when using this method that it can result in a runtime error. There is also a subString() method in the String class which returns part of a string and not just a single character. I'll leave you to investigate that method.

The concat() MethodTop

The concat() method will return a String object of the invoking string value appended with the argument string value. The following code and screenshot shows an example of using the String class concat() method:


/*
  The concat() method
*/
public class TestConcat {
    public static void main(String[] args) {
        String str1 = new String("java");
        System.out.println(str1.concat("Tutor"));
        System.out.println(str1);
    }
}

test concat() method

As you can see from the screenshot the class printed javaTutor to the console, which is the result of the concatenation of the String object referenced by str1 and the string literal "Tutor". After this we print out the value of the String object referenced by str1 which is still "java" as strings are immutable. Of course we could reassign str1 as follows but this is inefficient and string literal "java" is lost:


String str1 = new String("java");
str1 = str1.concat("Tutor"); // Reassign so "java" now lost in string constant pool
System.out.println(str1); // Will print javaTutor

The equals() MethodTop

The equals() method will return true if the invoking string has the the same character sequence as the argument string. This method is a valid override of the Object superclass equals() method. The following code and screenshot shows examples of using the String class equals() method:


/*
  The equals() method
*/
public class TestEquals {
    public static void main(String[] args) {
        String str1 = new String("aaa");
        String str2 = "aaa";
        String str3 = "AAA";
        System.out.println(str1 == str2);
        System.out.println(str1 == str3);
        System.out.println(str2 == str3);
        System.out.println(str1.equals(str2));
        System.out.println(str1.equals(str3));
        System.out.println(str2.equals(str3));
    }
}

test equals() method

The screenshot above shows the results of running the TestEquals class. When we check for object equality using the == relational operator all tests return false as no references refer to the same object. When we use the equals() method then the objects referenced by str1 and str2 return true as these objects do indeed have the same character sequence. Incidentally there is also an equalsIgnoreCase() method in the String class which would return true for the last 3 tests. I'll leave it for you to investigate this method :)

The length() MethodTop

The length() method will return the length of the invoking string. The following code and screenshot shows an example of using the String class length() method:


/*
  The length() method
*/
public class TestLength {
    public static void main(String[] args) {
        String str1 = new String("java");
        for (int i=0; i<str1.length(); i++) {
           System.out.println("char at position: " + i + " is " + str1.charAt(i));
        }
    }
}

test length() method

The screenshot above shows the results of running the TestLength class. We are using the length() method for our loop condition. This way we can ensure we never go past the end of our string and this also means we can use the charAt() method with the loop counter knowing we are not going to end up with a StringIndexOutOfBoundsException exception.

The replace() MethodTop

The replace() method will return a String object of the invoking string value where any occurrences of the first argument char value are replaced with occurrences of the second argument char value. The following code and screenshot shows an example of using the String class replace() method:


/*
  The replace() method
*/
public class TestReplace {
    public static void main(String[] args) {
        String str1 = new String("java");
        System.out.println(str1.replace("a", "i"));
        System.out.println(str1);
    }
}

test replace() method

As you can see from the screenshot the class printed jivi5 to the console, which is the result of replacing all occurrences of 'a' in the String object referenced by str1 with 'i'. After this we print out the value of the String object referenced by str1 which is still "java" as strings are immutable. Of course we could reassign str1 as follows but this is inefficient and string literal "java" is lost:


String str1 = new String("java");
str1 = str1.replace("a", "i"); // Reassign so "java" now lost in string constant pool
System.out.println(str1); // Will print jivi6
        

The toString() MethodTop

The toString() method will returns a string description of the object which is the value of the invoking string. This method is a valid override of the Object superclass toString() method. The following code and screenshot shows examples of using the String class toString() method:


/*
  The toString() method
*/
public class TestToString {
    public static void main(String[] args) {
        String str1 = new String("AAA");
        String str2 = "aaa";
        System.out.println(str1.toString());
        System.out.println(str2.toString());
    }
}

test toString() method

The screenshot above shows the results of running the TestToString class. The method passes back the contents of the String object.

Lesson 1 Complete

We began our studies of of the java API by looking at the predefined String object and some of the methods available for use with this class.

What's Next?

We learn about the predefined StringBuilder object and some of the methods available for use with this class.

go to home page Homepage go to top of page Top