Related
The Java Language Specification states that
When the intern method is invoked, if the pool already contains a
string equal to this String object as determined by the
equals(java.lang.Object) method, then the string from the pool is
returned
In the following code snippet:
class StringPoolTest {
public static void main(String[] args) {
String first = "string";
String second = new String("string");
String third = "string".intern();
System.out.println(System.identityHashCode(first));
System.out.println(System.identityHashCode(second));
System.out.println(System.identityHashCode(third));
}
}
Output:
989184670
268130470
989184670
I added a String object first to the pool (assigning a String literal to the reference) and explicitly created second using a String constructor.
There are now two identical character sequences in the pool.
I wanted to see which one would be returned when calling intern. Since the method hashCode is overridden for the class String, I used System.identityHashCode to see exactly which two String references were the same.
Clearly, intern returned the reference to the object created using a String literal. Why is this so? Are there any rules regarding which reference is returned in the case of multiple identical String objects in the pool?
When a string literal(without using new Operator) is created, the JVM checks whether that String exists in the internal list or not. If it already exists in the list, then it does not create a new String and it uses reference to the existing String Object.
JVM does this type of checking internally for String literal but not for String object, which it creates through 'new' keyword i.e. using new always a new string is returned.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
I do not understand why System.out.println(name) outputs Sam without being affected by the method's concat function, while System.out.println(names) outputs Sam4 as a result of the method's append method. Why is StringBuilder affected and not String? Normally, calling methods on a reference to an object affects the caller, so I do not understand why the String result remains unchanged. Thanks in advance
public static String speak(String name) {
name = name.concat("4");
return name;
}
public static StringBuilder test(StringBuilder names) {
names = names.append("4");
return names;
}
public static void main(String[] args) {
String name = "Sam";
speak(name);
System.out.println(name); //Sam
StringBuilder names = new StringBuilder("Sam");
test(names);
System.out.println(names); //Sam4
}
Because when you call speak(name);, inside speak when you do
name = name.concat("4");
it creates a new object because Strings are immutable. When you change the original string it creates a new object,I agree that you are returning it but you are not catching it.
So essentially what you are doing is :
name(new) = name(original) + '4'; // but you should notice that both the names are different objects.
try
String name = "Sam";
name = speak(name);
Of course now I think there is no need to explain why it's working with StringBuilder unless if you don't know that StringBuilder is mutable.
Looking at the Javadoc for String, one will read that
[...] String objects are immutable [...].
This means concat(String) does not change the String itself, but constructs a new String.
StringBuilders, on the other hand, are mutable. By calling append(CharSequence), the object itself is mutated.
Because String is immutable and hence String#concat does not modify the original String instance, it only returns a new String while the original is left unmodified, while StringBuilder is mutable and the change is reflected in the StringBuilder instance passed as parameter.
Okay, what is speak method doing?
First of all,
name.concat("4");
creates new object, which is equal to name, concatenated with "4".
So, the line
name = name.concat(4);
redefines local (for speak method) variable name.
Then you return the reference to this new value with
return name;
So, the original variable, passed within method is not modified, but the method returns modified value.
In the test method you actually modify variable without modifying the reference (the StringBuilder class is mutable, so variable if this type can be modified).
Then we can see another question arising: why StringBuilder.append returns value, where it can seem redundant. The answer to this question lies in the description of "builder" pattern, for which it is the usual way of implementing modification methods. See wikipedia on Builder pattern.
String is immutable in java. As soon as you invoke concat method on name. A new string is created and while you are playing with the old reference in System.out.println(name).If you want to use the modified string you should explicitly return the reference.
While StringBuilder is mutable and it returns the same reference always.
When you invoke speak(name) it computes the new value, but discards it.
If you replace it with
name = speak(name);
the result will be the one you expect.
With the StringBuilder, the object you pass is mutable: so
names.append(names);
changes the state of the current object (it also returns a reference to the same object, which is just a convenience to allow you to write code like names.append(...).append(...) etc.). So in the case of the StringBuilder, the object you are referencing when you call the method has actually changed, hence you see the changes.
In your method speak, the concat method returns a new String, the original object it was called on is unchanged (strings are immutable). As documented:
If the length of the argument string is 0, then this String object is returned. Otherwise, a String object is returned that represents a character sequence that is the concatenation of the character sequence represented by this String object and the character sequence represented by the argument string.
Calling name.concat("4") is the equivalent of name + "4".
In your test method the append method modifies the content of the StringBuilder. As documented:
The principal operations on a StringBuilder are the append and insert methods, which are overloaded so as to accept data of any type. Each effectively converts a given datum to a string and then appends or inserts the characters of that string to the string builder. The append method always adds these characters at the end of the builder; the insert method adds the characters at a specified point.
In your main method both name and names are still the same object as before the method call, but the content of name is unchanged as strings are immutable, while the content of names has been changed.
If instead you had used the return values of both methods, then you would have the result you were expecting.
First of all, String is an immutable class in Java. An immutable class is simply a class whose instances cannot be modified. All information in an instance is initialized when the instance is created and the information can not be modified.
Second, in java parameters are sent by values and not by reference.
In your method 'test' you don't need names = names.append("4"), instead names.append("4") will be enough .
If you check java docs for String object, you will see that most of the methods there, including concat, will generate a new String.
So to have on output Sam4 also for the String, you will need in main method to have this name = speak(name).
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
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
.
For more details check this
Conclusion:
You don't need to re-assign the value again to StringBuilder as it is already a reference
test method should be
public static void test(StringBuilder names) {
names.append("4");
}
but speak should be
String name = "Sam";
name = speak(name);
I'm a C++ guy learning Java. I'm reading Effective Java and something confused me. It says never to write code like this:
String s = new String("silly");
Because it creates unnecessary String objects. But instead it should be written like this:
String s = "No longer silly";
Ok fine so far...However, given this class:
public final class CaseInsensitiveString {
private String s;
public CaseInsensitiveString(String s) {
if (s == null) {
throw new NullPointerException();
}
this.s = s;
}
:
:
}
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
Why is the first statement ok? Shouldn't it be
CaseInsensitiveString cis = "Polish";
How do I make CaseInsensitiveString behave like String so the above statement is OK (with and without extending String)? What is it about String that makes it OK to just be able to pass it a literal like that? From my understanding there is no "copy constructor" concept in Java?
String is a special built-in class of the language. It is for the String class only in which you should avoid saying
String s = new String("Polish");
Because the literal "Polish" is already of type String, and you're creating an extra unnecessary object. For any other class, saying
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
is the correct (and only, in this case) thing to do.
I believe the main benefit of using the literal form (ie, "foo" rather than new String("foo")) is that all String literals are 'interned' by the VM. In other words it is added to a pool such that any other code that creates the same string will use the pooled String rather than creating a new instance.
To illustrate, the following code will print true for the first line, but false for the second:
System.out.println("foo" == "foo");
System.out.println(new String("bar") == new String("bar"));
Strings are treated a bit specially in java, they're immutable so it's safe for them to be handled by reference counting.
If you write
String s = "Polish";
String t = "Polish";
then s and t actually refer to the same object, and s==t will return true, for "==" for objects read "is the same object" (or can, anyway, I"m not sure if this is part of the actual language spec or simply a detail of the compiler implementation-so maybe it's not safe to rely on this) .
If you write
String s = new String("Polish");
String t = new String("Polish");
then s!=t (because you've explicitly created a new string) although s.equals(t) will return true (because string adds this behavior to equals).
The thing you want to write,
CaseInsensitiveString cis = "Polish";
can't work because you're thinking that the quotations are some sort of short-circuit constructor for your object, when in fact this only works for plain old java.lang.Strings.
String s1="foo";
literal will go in pool and s1 will refer.
String s2="foo";
this time it will check "foo" literal is already available in StringPool or not as now it exist so s2 will refer the same literal.
String s3=new String("foo");
"foo" literal will be created in StringPool first then through string arg constructor String Object will be created i.e "foo" in the heap due to object creation through new operator then s3 will refer it.
String s4=new String("foo");
same as s3
so System.out.println(s1==s2);// **true** due to literal comparison.
and System.out.println(s3==s4);// **false** due to object
comparison(s3 and s4 is created at different places in heap)
Strings are special in Java - they're immutable, and string constants are automatically turned into String objects.
There's no way for your SomeStringClass cis = "value" example to apply to any other class.
Nor can you extend String, because it's declared as final, meaning no sub-classing is allowed.
Java strings are interesting. It looks like the responses have covered some of the interesting points. Here are my two cents.
strings are immutable (you can never change them)
String x = "x";
x = "Y";
The first line will create a variable x which will contain the string value "x". The JVM will look in its pool of string values and see if "x" exists, if it does, it will point the variable x to it, if it does not exist, it will create it and then do the assignment
The second line will remove the reference to "x" and see if "Y" exists in the pool of string values. If it does exist, it will assign it, if it does not, it will create it first then assignment. As the string values are used or not, the memory space in the pool of string values will be reclaimed.
string comparisons are contingent on what you are comparing
String a1 = new String("A");
String a2 = new String("A");
a1 does not equal a2
a1 and a2 are object references
When string is explicitly declared, new instances are created and their references will not be the same.
I think you're on the wrong path with trying to use the caseinsensitive class. Leave the strings alone. What you really care about is how you display or compare the values. Use another class to format the string or to make comparisons.
i.e.
TextUtility.compare(string 1, string 2)
TextUtility.compareIgnoreCase(string 1, string 2)
TextUtility.camelHump(string 1)
Since you are making up the class, you can make the compares do what you want - compare the text values.
The best way to answer your question would be to make you familiar with the "String constant pool". In java string objects are immutable (i.e their values cannot be changed once they are initialized), so when editing a string object you end up creating a new edited string object wherease the old object just floats around in a special memory ares called the "string constant pool". creating a new string object by
String s = "Hello";
will only create a string object in the pool and the reference s will refer to it, but by using
String s = new String("Hello");
you create two string objects: one in the pool and the other in the heap. the reference will refer to the object in the heap.
You can't. Things in double-quotes in Java are specially recognised by the compiler as Strings, and unfortunately you can't override this (or extend java.lang.String - it's declared final).
- How do i make CaseInsensitiveString behave like String so the above statement is ok (with and w/out extending String)? What is it about String that makes it ok to just be able to pass it a literal like that? From my understanding there is no "copy constructor" concept in Java right?
Enough has been said from the first point. "Polish" is an string literal and cannot be assigned to the CaseInsentiviveString class.
Now about the second point
Although you can't create new literals, you can follow the first item of that book for a "similar" approach so the following statements are true:
// Lets test the insensitiveness
CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");
assert cis5 == cis6;
assert cis5.equals(cis6);
Here's the code.
C:\oreyes\samples\java\insensitive>type CaseInsensitiveString.java
import java.util.Map;
import java.util.HashMap;
public final class CaseInsensitiveString {
private static final Map<String,CaseInsensitiveString> innerPool
= new HashMap<String,CaseInsensitiveString>();
private final String s;
// Effective Java Item 1: Consider providing static factory methods instead of constructors
public static CaseInsensitiveString valueOf( String s ) {
if ( s == null ) {
return null;
}
String value = s.toLowerCase();
if ( !CaseInsensitiveString.innerPool.containsKey( value ) ) {
CaseInsensitiveString.innerPool.put( value , new CaseInsensitiveString( value ) );
}
return CaseInsensitiveString.innerPool.get( value );
}
// Class constructor: This creates a new instance each time it is invoked.
public CaseInsensitiveString(String s){
if (s == null) {
throw new NullPointerException();
}
this.s = s.toLowerCase();
}
public boolean equals( Object other ) {
if ( other instanceof CaseInsensitiveString ) {
CaseInsensitiveString otherInstance = ( CaseInsensitiveString ) other;
return this.s.equals( otherInstance.s );
}
return false;
}
public int hashCode(){
return this.s.hashCode();
}
// Test the class using the "assert" keyword
public static void main( String [] args ) {
// Creating two different objects as in new String("Polish") == new String("Polish") is false
CaseInsensitiveString cis1 = new CaseInsensitiveString("Polish");
CaseInsensitiveString cis2 = new CaseInsensitiveString("Polish");
// references cis1 and cis2 points to differents objects.
// so the following is true
assert cis1 != cis2; // Yes they're different
assert cis1.equals(cis2); // Yes they're equals thanks to the equals method
// Now let's try the valueOf idiom
CaseInsensitiveString cis3 = CaseInsensitiveString.valueOf("Polish");
CaseInsensitiveString cis4 = CaseInsensitiveString.valueOf("Polish");
// References cis3 and cis4 points to same object.
// so the following is true
assert cis3 == cis4; // Yes they point to the same object
assert cis3.equals(cis4); // and still equals.
// Lets test the insensitiveness
CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");
assert cis5 == cis6;
assert cis5.equals(cis6);
// Futhermore
CaseInsensitiveString cis7 = CaseInsensitiveString.valueOf("SomethinG");
CaseInsensitiveString cis8 = CaseInsensitiveString.valueOf("someThing");
assert cis8 == cis5 && cis7 == cis6;
assert cis7.equals(cis5) && cis6.equals(cis8);
}
}
C:\oreyes\samples\java\insensitive>javac CaseInsensitiveString.java
C:\oreyes\samples\java\insensitive>java -ea CaseInsensitiveString
C:\oreyes\samples\java\insensitive>
That is, create an internal pool of CaseInsensitiveString objects, and return the corrensponding instance from there.
This way the "==" operator returns true for two objects references representing the same value.
This is useful when similar objects are used very frequently and creating cost is expensive.
The string class documentation states that the class uses an internal pool
The class is not complete, some interesting issues arises when we try to walk the contents of the object at implementing the CharSequence interface, but this code is good enough to show how that item in the Book could be applied.
It is important to notice that by using the internalPool object, the references are not released and thus not garbage collectible, and that may become an issue if a lot of objects are created.
It works for the String class because it is used intensively and the pool is constituted of "interned" object only.
It works well for the Boolean class too, because there are only two possible values.
And finally that's also the reason why valueOf(int) in class Integer is limited to -128 to 127 int values.
In your first example, you are creating a String, "silly" and then passing it as a parameter to another String's copy constructor, which makes a second String which is identical to the first. Since Java Strings are immutable (something that frequently stings people who are used to C strings), this is a needless waste of resources. You should instead use the second example because it skips several needless steps.
However, the String literal is not a CaseInsensitiveString so there you cannot do what you want in your last example. Furthermore, there is no way to overload a casting operator like you can in C++ so there is literally no way to do what you want. You must instead pass it in as a parameter to your class's constructor. Of course, I'd probably just use String.toLowerCase() and be done with it.
Also, your CaseInsensitiveString should implement the CharSequence interface as well as probably the Serializable and Comparable interfaces. Of course, if you implement Comparable, you should override equals() and hashCode() as well.
CaseInsensitiveString is not a String although it contains a String. A String literal e.g "example" can be only assigned to a String.
CaseInsensitiveString and String are different objects. You can't do:
CaseInsensitiveString cis = "Polish";
because "Polish" is a String, not a CaseInsensitiveString. If String extended CaseInsensitiveString String then you'd be OK, but obviously it doesn't.
And don't worry about the construction here, you won't be making unecessary objects. If you look at the code of the constructor, all it's doing is storing a reference to the string you passed in. Nothing extra is being created.
In the String s = new String("foobar") case it's doing something different. You are first creating the literal string "foobar", then creating a copy of it by constructing a new string out of it. There's no need to create that copy.
Just because you have the word String in your class, does not mean you get all the special features of the built-in String class.
when they say to write
String s = "Silly";
instead of
String s = new String("Silly");
they mean it when creating a String object because both of the above statements create a String object but the new String() version creates two String objects: one in heap and the other in string constant pool. Hence using more memory.
But when you write
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
you are not creating a String instead you are creating an object of class CaseInsensitiveString. Hence you need to use the new operator.
If I understood it correctly, your question means why we cannot create an object by directly assigning it a value, lets not restrict it to a Wrapper of String class in java.
To answer that I would just say, purely Object Oriented Programming languages have some constructs and it says, that all the literals when written alone can be directly transformed into an object of the given type.
That precisely means, if the interpreter sees 3 it will be converted into an Integer object because integer is the type defined for such literals.
If the interpreter sees any thing in single quotes like 'a' it will directly create an object of type character, you do not need to specify it as the language defines the default object of type character for it.
Similarly if the interpreter sees something in "" it will be considered as an object of its default type i.e. string. This is some native code working in the background.
Thanks to MIT video lecture course 6.00 where I got the hint for this answer.
In Java the syntax "text" creates an instance of class java.lang.String. The assignment:
String foo = "text";
is a simple assignment, with no copy constructor necessary.
MyString bar = "text";
Is illegal whatever you do because the MyString class isn't either java.lang.String or a superclass of java.lang.String.
First, you can't make a class that extends from String, because String is a final class. And java manage Strings differently from other classes so only with String you can do
String s = "Polish";
But whit your class you have to invoke the constructor. So, that code is fine.
I would just add that Java has Copy constructors...
Well, that's an ordinary constructor with an object of same type as argument.
String is one of the special classes in which you can create them without the new Sring part
it's the same as
int x = y;
or
char c;
String str1 = "foo";
String str2 = "foo";
Both str1 and str2 belongs to tha same String object, "foo", b'coz Java manages Strings in StringPool, so if a new variable refers to the same String, it doesn't create another one rather assign the same alerady present in StringPool.
String str1 = new String("foo");
String str2 = new String("foo");
Here both str1 and str2 belongs to different Objects, b'coz new String() forcefully create a new String Object.
It is a basic law that Strings in java are immutable and case sensitive.
Java creates a String object for each string literal you use in your code. Any time "" is used, it is the same as calling new String().
Strings are complex data that just "act" like primitive data. String literals are actually objects even though we pretend they're primitive literals, like 6, 6.0, 'c', etc. So the String "literal" "text" returns a new String object with value char[] value = {'t','e','x','t}. Therefore, calling
new String("text");
is actually akin to calling
new String(new String(new char[]{'t','e','x','t'}));
Hopefully from here, you can see why your textbook considers this redundant.
For reference, here is the implementation of String: http://www.docjar.com/html/api/java/lang/String.java.html
It's a fun read and might inspire some insight. It's also great for beginners to read and try to understand, as the code demonstrates very professional and convention-compliant code.
Another good reference is the Java tutorial on Strings:
http://docs.oracle.com/javase/tutorial/java/data/strings.html
In most versions of the JDK the two versions will be the same:
String s = new String("silly");
String s = "No longer silly";
Because strings are immutable the compiler maintains a list of string constants and if you try to make a new one will first check to see if the string is already defined. If it is then a reference to the existing immutable string is returned.
To clarify - when you say "String s = " you are defining a new variable which takes up space on the stack - then whether you say "No longer silly" or new String("silly") exactly the same thing happens - a new constant string is compiled into your application and the reference points to that.
I dont see the distinction here. However for your own class, which is not immutable, this behaviour is irrelevant and you must call your constructor.
UPDATE: I was wrong!
I tested this and realise that my understanding is wrong - new String("Silly") does indeed create a new string rather than reuse the existing one. I am unclear why this would be (what is the benefit?) but code speaks louder than words!
I use the == in the code below and prints out "Equals!", why? Can someone explain why these two different strings a and b are equal?
public class test
{
public static void main()
{
String a = "boy";
String b = "boy";
if(a == b)
{
System.out.println("Equals!");
}
else
{
System.out.println("Does not equal!");
}
}
}
This is due to String interning.
Java (The JVM) keeps a collection of String literals that is uses to save memory. So, whenever you create a String like so:
String s = "String";
Java 'interns' the string. However, if you create the String like so:
String s = new String("String");
Java will not automatically intern the String. If you created your strings this way, your code would produce different results.
A quick Google search reveals lots of good resources regarding String interning.
This article will explain it in details:
What is the difference between == and equals() in Java?
After the execution of String a =
“boy”; the JVM adds the
string “boy” to the string
pool and on the next line of the code, it
encounters String b = ”boy” again; in this case the JVM already
knows that this string is already
there in the pool, so it does not create a
new string. So both strings a and b point to the same string what means they
point to the same reference.
String a = "boy"; will create a new string object with value ("boy"), place it in the string pool and make a refer to it.
When the interpreter sees String b = "boy";, it first checks to see if string "boy" is present in the string pool, since it is present, no new object is created and b is made to refer to the same object that a is referring to.
Since both references contain the same content they pass the equality test.
Because the run time will have a string pool and when you need to assign a new constant string, the run time look inside the pool, if the pool contains it, then they set the variable point to the same String object inside the pool.
But you should never depends on this to check for content string equals. You should use the method: equals
Whenever we create a string like below :
String str1 = "abc";
String str2 = "abc";
JVM will check the str2 = "abc" in the string constant pool, if it is present then it wont create a new String instead it point to the string one in the string constant pool.
But in case of this String str = new String("abc"); it will always create a new String Object but we can use intern() function to force JVM to look into the string constant pool.
As rightly explained above, in the case of '==' comparison, the runtime will look into the String pool for the existence of the string. However, it very much possible that during garbage collection, or during memory issues, the virtual machine might destroy the string pool. The "==" operator therefor might or might not return the correct value.
Lesson - Always use equals() for comparison.
We normally create objects using the new keyword, like:
Object obj = new Object();
Strings are objects, yet we do not use new to create them:
String str = "Hello World";
Why is this? Can I make a String with new?
In addition to what was already said, String literals [ie, Strings like "abcd" but not like new String("abcd")] in Java are interned - this means that every time you refer to "abcd", you get a reference to a single String instance, rather than a new one each time. So you will have:
String a = "abcd";
String b = "abcd";
a == b; //True
but if you had
String a = new String("abcd");
String b = new String("abcd");
then it's possible to have
a == b; // False
(and in case anyone needs reminding, always use .equals() to compare Strings; == tests for physical equality).
Interning String literals is good because they are often used more than once. For example, consider the (contrived) code:
for (int i = 0; i < 10; i++) {
System.out.println("Next iteration");
}
If we didn't have interning of Strings, "Next iteration" would need to be instantiated 10 times, whereas now it will only be instantiated once.
Strings are "special" objects in Java. The Java designers wisely decided that Strings are used so often that they needed their own syntax as well as a caching strategy. When you declare a string by saying:
String myString = "something";
myString is a reference to String object with a value of "something". If you later declare:
String myOtherString = "something";
Java is smart enough to work out that myString and myOtherString are the same and will store them in a global String table as the same object. It relies on the fact that you can't modify Strings to do this. This lowers the amount of memory required and can make comparisons faster.
If, instead, you write
String myOtherString = new String("something");
Java will create a brand new object for you, distinct from the myString object.
String a = "abc"; // 1 Object: "abc" added to pool
String b = "abc"; // 0 Object: because it is already in the pool
String c = new String("abc"); // 1 Object
String d = new String("def"); // 1 Object + "def" is added to the Pool
String e = d.intern(); // (e==d) is "false" because e refers to the String in pool
String f = e.intern(); // (f==e) is "true"
//Total Objects: 4 ("abc", c, d, "def").
Hope this clears a few doubts. :)
We usually use String literals to avoid creating unnecessary objects. If we use new operator to create String object , then it will create new object everytime .
Example:
String s1=“Hello“;
String s2=“Hello“;
String s3= new String(“Hello“);
String s4= new String(“Hello“);
For the above code in memory :
It's a shortcut. It wasn't originally like that, but Java changed it.
This FAQ talks about it briefly. The Java Specification guide talks about it also. But I can't find it online.
String is subject to a couple of optimisations (for want of a better phrase). Note that String also has operator overloading (for the + operator) - unlike other objects. So it's very much a special case.
In Java, Strings are a special case, with many rules that apply only to Strings. The double quotes causes the compiler to create a String object. Since String objects are immutable, this allows the compiler to intern multiple strings, and build a larger string pool. Two identical String constants will always have the same object reference. If you don't want this to be the case, then you can use new String(""), and that will create a String object at runtime. The intern() method used to be common, to cause dynamically created strings to be checked against the string lookup table. Once a string in interned, the object reference will point to the canonical String instance.
String a = "foo";
String b = "foo";
System.out.println(a == b); // true
String c = new String(a);
System.out.println(a == c); // false
c = c.intern();
System.out.println(a == c); // true
When the classloader loads a class, all String constants are added to the String pool.
Well the StringPool is implemented using The Hashmap in java. If we are creating always with a new keyword its not searching in String Pool and creating a new memory for it which might be needed later if we have a memory intensive operation running and if we are creating all the strings with new keyword that would affect performance of our application. So its advisable to not to use new keywords for creating string because then only it will go to String pool which in turn is a Hashmap ,(memory saved , imagine if we have lots of strings created with new keyword ) here it will be stored and if the string already exists the reference of it(which would usually reside in Stack memory) would be returned to the newly created string.
So its done to improve performance .
Syntactic sugar. The
String s = new String("ABC");
syntax is still available.
You can still use new String("string"), but it would be harder to create new strings without string literals ... you would have to use character arrays or bytes :-) String literals have one additional property: all same string literals from any class point to same string instance (they are interned).
There's almost no need to new a string as the literal (the characters in quotes) is already a String object created when the host class is loaded. It is perfectly legal to invoke methods on a literal and don, the main distinction is the convenience provided by literals. It would be a major pain and waste of tine if we had to create an array of chars and fill it char by char and them doing a new String(char array).
Feel free to create a new String with
String s = new String("I'm a new String");
The usual notation s = "new String"; is more or less a convenient shortcut - which should be used for performance reasons except for those pretty rare cases, where you really need Strings that qualify for the equation
(string1.equals(string2)) && !(string1 == string2)
EDIT
In response to the comment: this was not intended to be an advise but just an only a direct response to the questioners thesis, that we do not use the 'new' keyword for Strings, which simply isn't true. Hope this edit (including the above) clarifies this a bit. BTW - there's a couple of good and much better answers to the above question on SO.
The literal pool contains any Strings that were created without using the keyword new.
There is a difference : String without new reference is stored in String literal pool and String with new says that they are in heap memory.
String with new are elsewhere in memory just like any other object.
Because String is an immutable class in java.
Now why it is immutable?
As String is immutable so it can be shared between multiple threads and we dont need to synchronize String operation externally.
As String is also used in class loading mechanism. So if String was mutable then java.io.writer could have been changed to abc.xyz.mywriter
TString obj1 = new TString("Jan Peter");
TString obj2 = new TString("Jan Peter");
if (obj1.Name == obj2.Name)
System.out.println("True");
else
System.out.println("False");
Output:
True
I created two separate objects, both have a field(ref) 'Name'. So even in this case "Jan Peter" is shared, if I understand the way java deals..