Bogotobogo
contact@bogotobogo.com
- Java Tutorial Home
- Basics - Compiling and Launching
- Inner Classes
- Constructor
- Enums
- Statics
- Default and Protected
- Polymorphism
- Exception Handling
- Exception Handling II
- String Class
- Threads
- Threads II - State Transition
- Threads III - Synchronization
- Object Class
- File I/O
- Serialization
- ArrayList
- Autoboxing
- Java Graphics Interface I - Basics
- Java Graphics Interface II - Labels, Text Fields, Layouts
- Java Graphics Interface III - paintComponent
- TCP Sockets Server/Client
Handling characters in supported through three final classes: String, StringBuilder and StringBuffer.
StringBuilder class was added to the API, to provide faster, nonsynchronized StringBuffer capability. The StringBuilder class has exactly the same methods as the old StringBuffer class, but StringBuilder is faster because its methods aren't synchronized. Both classes give us String-like object that handle some of the String class's shortcomings such as immutability.
The String class implement immutable character strings, which are read-only once the string has been created and initialized, whereas StringBuilder class implements dynamic character strings. The StringBuffer class is a thread-safe version of the StringBuilder class.
A String object can never be changed. But what is happening when a String object seems to be changing?
Each character in a string is a 16-bit Unicode character. Since Unicode characters are 16-bit, international set of characters is easily represented in Unicode.
Because strings are object, we can create an instance of a String with new keyword.
String s = new String();
This creates a new object of class String, and assigns it to the reference variable s. Let's give it to some value:
s = "Java";
Actually, because String class has lots of constructors, we can do the same in one line:
String s = "Java";
Another String object:
String s2 = s;
So, s and s2 refer the same object.
How about the following line?
s = s.concat(" String");
Aren't Strings immutable?
Let's look at the following example.
public class StringTest {
public static void main(String[] args) {
String s = "Java"; // (1)
String s2 = s; // (2)
s = s.concat(" String"); // (3)
System.out.println("s = " + s);
System.out.println("s2 = " + s2);
}
}
Output is:
s = Java String s2 = Java
On the heap, we have two String objects: "Java" and "Java String". Also we have two reference variables: s refers to "Java String" and s2 refers to "Java" starting from line (2). So, at the line (3), the old String "Java" did not changed to "Java String" instead a new String was created and initialize with "Java String".
How about the output from the following code?
public class StringTest {
public static void main(String[] args) {
String s = "Java";
String s2 = s;
s = s.concat(" String");
System.out.println("s = " + s);
System.out.println("s2 = " + s2);
s.concat(" is Immutable!"); // What's happening?
System.out.println("s = " + s);
}
}
Output is:
s = Java String s2 = Java s = Java String
A new String is created but it has not reference variable which can point to the newly create string.
s.concat(" is Immutable!"); // What's happening?
So, we do have a String object, "Java String is Immutable!". But we do not have the reference which can refer to the object. New String object has been created but we lost it. It's somewhere on the heap. But we do not know how we can get it.
How about this?
String s = "Android";
s.toUpperCase();
System.out.println("s = " + s);
The output is still:
s = Android
Same result from the following code:
s = "Android";
s.replace('d','D');
System.out.println("s = " + s);
The output is still:
s = Android
How about this?
s = "Android";
s = s.concat(" is getting better");
System.out.println("s = " + s);
Output is:
s = Android is getting better
Finally we get a new string!
But we lost our old String object, "Android".
What's the output from the following code?
String s1 = "North ";
String s2 = s1 + "East ";
s1.concat("South ");
s2.concat(s1);
s1 += "West ";
System.out.println(s1 + " " + s2);
Output is
North West North East
We have two reference variables, s1 and s2. We had a total of eight String objects created as follows in order: "North", "East" (lost), "North East", "South" (lost), "North South" (lost), "North East North" (lost), "West" (lost), "North West" (at this point, the first object "North" is lost). So, only two of the eight String objects are not lost in this process.
As application grows, it's very common for String literals to occupy large amounts of memory, and there are often a lot of redundant String literals on the heap. To make Java more memory efficient, the JVM sets aside a special area of memory called String constant pool.
When the compiler encounters a String literal, it checks the pool to see if an identical String already exists. If there is a match, the reference to the new literal is directed to the existing String, and as a result, no new String literal object is created.
If several reference variables refer to the same String without even knowing it, it would be very bad if any of them could change the String's value.
The reason the String class is marked final is to prevent somebody from overriding the behavior of any of the String method. In that way, we can rest assured that the String objects we are counting on to be immutable, will remain immutable.
When we do
String s = "Java";
we are create one String object and one reference variable and the String object "Java" will go in the pool and s will refer to it.
But when we do
String s = new String("Java");
Java will create a new String object in normal (which is not pool) memory because we are using new keyword. The reference variable s will refer to it. The literal "Java" will be placed in the pool.
- char charAt(int index)
This method returns the character located at the String's specified index.
String s = "Michelangelo"; System.out.println(s.charAt(4)); // output is 'e'
- String concat(String s)
This method returns a String with the value of the String passed in to the method appended to the end of the String used to invoke the method.
String s = "Dali: "; System.out.println(s.concat("Persistence of Memory")); // output is "Dali: Persistence of Memory" - boolean equalsIgnoreCase(String s)
This method returns a boolean value depending on whether the value of the String in the argument is the same as the value of the String used to invoke the method. This method will return true even when characters in the String objects being compared have different cases.
String s = "Klimt"; System.out.println(s.equalsIgnoreCase("klimt")); // "true" System.out.println(s.equalsIgnoreCase("klit")); // "false" - int length()
This method returns the length of the String used to invoke the method.
String s = "Van Gogh"; System.out.println(s.length()); // output is "8"
- String replace(char old, char new)
This method returns a String whose value is that of the String used to invoke the method, updated so that any occurence of the char in the first argument is replaced by the char in the second argument.
String s = "Rembrandt"; System.out.println(s.replace('r','R')); // output is "RembRandt" - String substring(int begin)
String substring(int begin, int end)
This method is used to return a part of the String used to invoke the method.
String s = "Velasquez"; System.out.println(s.substring(1)); // output is "elasquez" System.out.println(s.substring(1,4)); // output is "ela"
- String toLowerCase()
This method returns a String whose value is the String used to invoke the method, but with any uppercase characters converted to lowercase.
String s = "Rousseau"; System.out.println(s.toLowerCase()); // output is "rousseau"
- String toString()
This method returns the value of the String used to invoke the method. Why do we need such method? All objects in Java must have a toString() method, which typically returns a String that in some meaningful way of describing the object in question. In the case of a String object, what is more meaningful way than the String's value?
String s = "Renoir"; System.out.println(s.toString()); // output is "Renoir"
- String toUpperCase()
This method returns a String whose value is the String used to invoke the method, but with lowercase characters converted to uppercase.
String s = "goya"; System.out.println(s.toUpperCase()); // output is "GOYA"
- String trim()
This method returns a String whose value is the String used to invoke the method, but with any leading or trailing blank spaces removed.
String s = " Rubens "; System.out.println(s.trim() + ": Debarquement de Marie de Medicis"); // output is "Rubens: Debarquement de Marie de Medicis"
- Java Tutorial Home
- Basics - Compiling and Launching
- Inner Classes
- Constructor
- Enums
- Default and Protected
- Polymorphism
- Exception Handling
- Exception Handling II
- String Class
- Statics
- Threads
- Threads II - State Transition
- Threads III - Synchronization
- Object Class
- File I/O
- Serialization
- ArrayList
- Autoboxing
- Java Graphics Interface I - Basics
- Java Graphics Interface II - Labels, Text Fields, Layouts
- Java Graphics Interface III - paintComponent
- TCP Sockets Server/Client