Friday, November 30, 2012

Strings in Java

Differences between creating String as new() and literal assigning?
Described as code, the question transforms in this:
String a = "abc";
String c = new String("abc");


Just a note, which is basic for all comments below – String in Java is immutable.
When we create string with new() Operator, it’s created in heap and not added into string pool while String created using literal are created in String pool itself which exists in PermGen area of heap.

Lets look some functionality differences:

String a = "abc";
String b = "abc";
System.out.println(a == b);  // True

String c = new String("abc");
String d = new String("abc");
System.out.println(c == d);  // False (in most JVM)

System.out.println( c.equals(d) );  // true
System.out.println( a.equals(d) );  // true


When we use “abc” string as literal, the string data (the array of characters) is written in the memory only one time. So object a and object b are the same.

When new operator is used, it allocates new Object in heap every time it is “called”. So the result of “c == d” is false (this is not guaranteed to be the rule on non Sun VM, because it depends on the java virtual machine, which is used.)

Creating strings
See the code:
for (int i = 0; i < 10; i++) {
  System.out.println( "this String object is created only once" );
  System.out.println( new String( "new String object is created on every cycle iteration" ) );
}



String.intern() method
It returns instance of the string located in String pool. If there is no such object there, it is created.

Note: for synchronization with String objects
Lets see this code:
String syncObject = “sync-string”;
synchronized( syncObject ){
// do something
}

If I use this approach of synchronization, I get some hazards of sync conflicts. If  “sync-object” is used for synchronization elsewhere, it could get the other code and possibly deadlock the application. Using the same String constant for sync could easily happened, if someone copy-pastes that code. Creating the syncObject with new is slightly better solution, but also relies on non-documented rule for placing the same new objects in different objects in heap. Best solution is not using immutable objects for sync objects.

How does substring () inside String works?
If you call substring on an existing object this will result in a new String object being created (Strings are immutable), which shares the char[] of the existing String.

Is literal string assigning better than new String( String )  in all cases?
No in all cases. Here is an example:
Code:
System.out.println( “Write the full filename” );
String filename = System.in.readline(); // the string is allocated in heap
// let filename be:
“C:\Documents and Settings\veeeery_long_path\b21fef7be6585b5.lrprev”
// make some processing of filename
String driveLetter = filename.substring( 0, 2 ); // “C:”
filename = null; // indicate that Java could garbage-collect the memory from filename


After that, the whole filename contains in memory in char[] form. It could not be removed because of the first 2 characters, used by driveLetter;

If we create driveLetter in this way:
String driveLetter = new String( filename.substring( 0, 2 ) ); // “C:”

The “C:” char[] is copied to a new location and after that filename variable could be garbage-collected. It makes the code much more memory effective. But you have to decide where to use this way. For most cases literal assigning is better.

No comments:

Post a Comment