== references to memory location, i.e if the both the objects share the same memory
.equals(...) references to the value of the object i.e if the both the objects has the exactly the same value.
Example: String name = "Smit";
In the memory | name || Smit |
So whenever a new literal is created, Java(JVM) will go a check for its existance in the mrmory and it there is no, it will create new.
name = "Smit Shah";
In the memory |name || Smit| | name || Smit Shah|
so everytime program makes changes to the String variable, it will create a new instance in the memory and it will cause HEAP size to increase
String n = "Smit";
String m = n;
is(m == n) //yes, because they both are the same location
is(m.equals(n) //yes, they both have value "Smit"
m = m + " Shah";
is(m == n) //no, because they both are referencing at different locations
is(m.equals(n) //no, they both have different value "Smit" and "Smit Shah"
String x = "Smit";
is(x == n) //yes, because JVM will search for the value in memory, if found it will reference x to that memory location and if not it will create new.
is(x.equals(n)) //yes, they both have same value "Smit"
Example: String fname = new String("Smit");
In the memory |name || Smit| | fname || Smit|
it will create a new location, and will not check if the value exists.
String lname = fanme;
is lname == fname? yes, why because it is sharing the same memory. but as soon as you make change to any(lname, fname) it will not be == anymore.
String s = "s";
String sn = new String(s);
String snw = sn;
if(s == sn) //false, why because they both are new instance in the location.
if(sn == snw) //true, because they both share the same location in the memory
sn += "s";
if(sn == snw) //false, as there was a change in sn, thus sn has a new location in memory.
One of its biggest strength Immutability is also biggest problem of Java String if not used correctly. Many times we create a String and then perform a lot of operation on them e.g. converting a string into uppercase, lowercase , getting substring out of it , concatenating with other string etc. Since String is an immutable class every time a new String is created and the older one is discarded, which creates lots of temporary garbage in the heap.
insert
andappend
are kind of method added to assit in updating the object
StringBuffer sb = new StringBuffer("Smit");
StringBuffer sb1 = new StringBuffer("Smit");
is(sb == sb1) //false, because they both have created a new instance of the object in the memory
is(sb.equals(sb1)) //false, MIND IT, you are comparing StringBuffer not the value of sb and sb1
is(sb.toString().equals(sb1.toString)) //true, as both have same value "Smit"
StringBuffer nsb = sb;
is(nsb == sb) //true, same memory location.
nsb.append("s");
is(nsb == sb) //true, because StringBuffer are mutable, they work as "PASS BY REFERENCE" so the value of nsb and sb will be "Smits"
is(nsb.equals(sb)) //true, because of PASS BY REFERENCE, the vaues of sb abd nsb are appended.
Case 4: Consider using new StringBuilder, it is a copy of StringBuffer but just that this is not syncnorised MUTABLE
StringBuilder are copy of StringBuffer they have exactly the same behaviour except one thing StringBuffer is very good with mutable String but it has one disadvantage all its public methods are synchronized which makes it thread-safe but same time slow. In JDK 5 they provided a similar class called StringBuilder in Java which is a copy of StringBuffer but without synchronization. Try to use StringBuilder whenever possible it performs better in most of the cases than StringBuffer class.
You may read more about this topic here