Tuesday 7 February 2017

String Interview Questions

1) What is string constant pool? String objects are most used data objects in Java. Hence, java has a special arrangement to store t... thumbnail 1 summary
1) What is string constant pool?

String objects are most used data objects in Java. Hence, java has a special arrangement to store the string objects. String Constant Pool is one such arrangement. String Constant Pool is the memory space in heap memory specially allocated to store the string objects created using string literals. In String Constant Pool, there will be no two string objects having the same content.
Whenever you create a string object using string literal, JVM first checks the content of the object to be created. If there exist an object in the string constant pool with the same content, then it returns the reference of that object. It doesn’t create a new object. If the content is different from the existing objects then only it creates new object.

2) What is special about string objects as compared to objects of other derived types?

One special thing about string objects is that you can create string objects without using new operator i.e using string literals. This is not possible with other derived types (except wrapper classes). One more special thing about strings is that you can concatenate two string objects using ‘+’. This is the relaxation java gives to string objects as they will be used most of the time while coding. And also java provides string constant pool to store the string objects.

3) What do you mean by mutable and immutable objects?

Immutable objects are like constants. You can’t modify them once they are created. They are final in nature. Where as mutable objects are concerned, you can perform modifications to them.

4) Why string objects are immutable in java?

String is immutable for several reasons, here is a summary:

  • Security: parameters are typically represented as String in network connections, database connection urls, usernames/passwords etc. If it were mutable, these parameters could be easily changed.
  • Synchronization and concurrency: making String immutable automatically makes them thread safe thereby solving the synchronization issues.
  • Caching: when compiler optimizes your String objects, it sees that if two objects have same value (a="test", and b="test") and thus you need only one string object (for both a and b, these two will point to the same object).
  • Class loading: String is used as arguments for class loading. If mutable, it could result in wrong class being loaded (because mutable objects change their state).

That being said, immutability of String only means you cannot change it using its public API. You can in fact bypass the normal API using reflection.

5) How many ways we can create the string object?

There are two ways to create the string object, by string literal and by new keyword.
We can create String object using new operator like any normal java class or we can use double quotes (string literal) to create a String object.
String str = new String("abc");
String str1 = "abc";

When we create a String using double quotes, JVM looks in the String pool to find if any other String is stored with same value. If found, it just returns the reference to that String object else it creates a new String object with given value and stores it in the String pool.
When we use new operator, JVM will create a new string object in normal(non pool) heap memory and the literal "abc" will be placed in the string constant pool. The variable str will refer to the object in heap(non pool).

6) Which one will you prefer among “==” and equals() method to compare two string objects?

I prefer equals() method because it compares two string objects based on their content. That provides more logical comparison of two string objects. If you use “==” operator, it checks only references of two objects are equal or not. It may not be suitable in all situations. So, rather stick to equals() method to compare two string objects.
String s1 = "JAVA";
 
String s2 = "JAVA";
s1 == s2 —> will return true as both are pointing to same object in the constant pool.
s1.equals(s2) —> will also return true as both are referring to same object.
String s1 = new String("JAVA");
 
String s2 = new String("JAVA");
s1 == s2 —> will return false because s1 and s2 are referring to two different objects in the memory.
s1.equals(s2) —> will return true as both the objects have same content.

7) What is Difference Between String , StringBuilder And StringBuffer Classes?

String
String is immutable  ( once created can not be changed )object  . The object created as a String is stored in the  Constant String Pool  .
Every immutable object in Java is thread safe ,that implies String is also thread safe . String can not be used by two threads simultaneously.
String  once assigned can not be changed.
String  demo = " hello " ;
// The above object is stored in constant string pool 
// and its value can not be modified.

demo="Bye" ;     //new "Bye" string is created in constant pool 
// and referenced by the demo variable            
// "hello" string still exists in string constant pool and its value 
// is not overrided but we lost reference to the  "hello"string  

StringBuffer
StringBuffer is mutable means one can change the value of the object . The object created through StringBuffer is stored in the heap . StringBuffer  has the same methods as the StringBuilder , but each method in StringBuffer is synchronized that is StringBuffer is thread safe .
Due to this it does not allow  two threads to simultaneously access the same method . Each method can be accessed by one thread at a time .
But being thread safe has disadvantages too as the performance of the StringBuffer hits due to thread safe property . Thus  StringBuilder is faster than the StringBuffer when calling the same methods of each class.
StringBuffer value can be changed , it means it can be assigned to the new value . Nowadays its a most common interview question ,the differences between the above classes .
String Buffer can be converted to the string by using
toString() method.
StringBuffer demo1 = new StringBuffer("Hello") ;
// The above object stored in heap and its value can be changed .
demo1=new StringBuffer("Bye");
// Above statement is right as it modifies the value 
// which is allowed in the StringBuffer

StringBuilder
StringBuilder  is same as the StringBuffer , that is it stores the object in heap and it can also be modified . The main difference between the StringBuffer and StringBuilder is that StringBuilder is also not thread safe.
StringBuilder is fast as it is not thread safe .  
StringBuilder demo2= new StringBuilder("Hello");
// The above object too is stored in the heap and its value can be 
// modified
demo2=new StringBuilder("Bye"); 
// Above statement is right as it modifies the value which is 
// allowed in the StringBuilder

8) How to create Immutable class?

To create immutable class in java, you have to do following steps.
  • Declare the class as final so it can’t be extended.
  • Make all fields private so that direct access is not allowed.
  • Don’t provide setter methods for variables
  • Make all mutable fields final so that it’s value can be assigned only once.
  • Initialize all the fields via a constructor performing deep copy.
  • Perform cloning of objects in the getter methods to return a copy rather than returning the actual object reference.
import java.util.HashMap;
import java.util.Iterator;

public final class FinalClassExample {

 private final int id;
 
 private final String name;
 
 private final HashMap testMap;
 
 public int getId() {
  return id;
 }


 public String getName() {
  return name;
 }

 /**
  * Accessor function for mutable objects
  */
 public HashMap getTestMap() {
  //return testMap;
  return (HashMap) testMap.clone();
 }

 /**
  * Constructor performing Deep Copy
  * @param i
  * @param n
  * @param hm
  */
 
 public FinalClassExample(int i, String n, HashMap hm){
  System.out.println("Performing Deep Copy for Object 
                initialization");
  this.id=i;
  this.name=n;
  HashMap tempMap=new HashMap();
  String key;
  Iterator it = hm.keySet().iterator();
  while(it.hasNext()){
   key=it.next();
   tempMap.put(key, hm.get(key));
  }
  this.testMap=tempMap;
 }
 
 
 /**
  * Constructor performing Shallow Copy
  * @param i
  * @param n
  * @param hm
  */
 /**
 public FinalClassExample(int i, String n, HashMap hm){
  System.out.println("Performing Shallow Copy for Object 
                initialization");
  this.id=i;
  this.name=n;
  this.testMap=hm;
 }
 */
 
 /**
  * To test the consequences of Shallow Copy and how to avoid it
         * with Deep Copy for creating immutable classes
  * @param args
  */
 public static void main(String[] args) {
  HashMap h1 = new HashMap();
  h1.put("1", "first");
  h1.put("2", "second");
  
  String s = "original";
  
  int i=10;
  
  FinalClassExample ce = new FinalClassExample(i,s,h1);
  
  //Lets see whether its copy by field or reference
  System.out.println(s==ce.getName());
  System.out.println(h1 == ce.getTestMap());
  //print the ce values
  System.out.println("ce id:"+ce.getId());
  System.out.println("ce name:"+ce.getName());
  System.out.println("ce testMap:"+ce.getTestMap());
  //change the local variable values
  i=20;
  s="modified";
  h1.put("3", "third");
  //print the values again
  System.out.println("ce id after local variable change:"
                +ce.getId());
  System.out.println("ce name after local variable change:"
                +ce.getName());
  System.out.println("ce testMap after local variable change
                :"+ce.getTestMap())
  
  HashMap hmTest = ce.getTestMap();
  hmTest.put("4", "new");
  
  System.out.println("ce testMap after changing variable 
                from accessor methods:"+ce.getTestMap());

 }

}
Output of the above immutable class in java example program is:

Performing Deep Copy for Object initialization
  • true
  • false
  • ce id:10
  • ce name:original
  • ce testMap:{2=second, 1=first}
  • ce id after local variable change:10
  • ce name after local variable change:original
  • ce testMap after local variable change:{2=second, 1=first}
  • ce testMap after changing variable from accessor methods:{2=second, 1=first}

Now let’s comment the constructor providing deep copy and uncomment the constructor providing shallow copy. Also uncomment the return statement in getTestMap() method that returns the actual object reference and then execute the program once again.

Performing Shallow Copy for Object initialization
  • true
  • true
  • ce id:10
  • ce name:original
  • ce testMap:{2=second, 1=first}
  • ce id after local variable change:10
  • ce name after local variable change:original
  • ce testMap after local variable change:{3=third, 2=second, 1=first}
  • ce testMap after changing variable from accessor methods:{3=third, 2=second, 1=first, 4=new}
  • As you can see from the output, HashMap values got changed because of shallow copy in the constructor and providing direct reference to the original object in the getter function.

No comments

Post a Comment