In java String can be created in 2 ways given below
String foo="Test";
String fooobj=new String("Test");
Everywhere it is mentioned about difference between these 2 ways of creating String. I want to know more about What are appropriate scenario's ,
where we should go for
String foo="Test";
And when to go for
String fooobj=new String("Test"); ?
The short answer: If you're in any doubt, you don't want new String("literal here"). If you need it, you'll know you need it, and why.
The long answer:
Essentially the only time you want to use new String("literal here") is if you want to ensure that the resulting string object is not == any other string object. Literals get interned automatically; strings created via new String("literal here") are not.
So why would you want that? The answer is you almost never would, because String instances are immutable, so you don't care if you're sharing a String instance with something else. Just about the only scenario I can imagine is if you had an API that accepted a String and you wanted to have a flag value other than null, and you wanted to check that flag/marker value via ==, like this:
public static final String MARKER = new String("Marker");
public void someFictionalMethod(String arg) {
if (arg == MARKER) {
// Take action on the marker
}
else {
// Take action on the string
}
}
...and even then I'd tend to find it a bit suspect and would explore other ways to do it.
It is never necessary to create a new String object with
String fooobj = new String("Test");
So, you should never do this. Just write String fooobj = "Test"; instead.
Class String is immutable. That means that the content of a String object cannot be changed after it has been constructed. It's never necessary to create an explicit copy of a string literal.
You should never use new String(). Anytime you create string in this way, new object in memory is created. If you write String s = "aaa", then there is a chance such object was already created in a given JVM, it is stored in string pool and thanks to that your variable will be just reference to that existing object - you safe memory in this way.
When you use the second approach, you actually rely on the first approach to initialize the constructor arguments.
So the question is if you could create the String object via first approach, why you spend extra effort to use the second approach ?
I don't see any scenary to use the second constructor style, so always insist in using the first approach.
There is a subtle differences between String object and string literal.
String s = "abc"; // creates one String object and one reference variable
In this simple case, "abc" will go in the pool and s will refer to it.
String s = new String("abc"); // creates two objects,and one reference variable
In this case, because we used the new keyword, Java will create a new String object in normal (non-pool) memory, and s will refer to it. In addition, the literal "abc" will be placed in the pool.
Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. For example:
String str = "abc";
is equivalent to:
String str = new String("abc");
You should avoid the second way to declare a string, for reasons explained into other answers
Related
I've been studying Java String for a while. The following questions are based on the below posts
Java String is special
Immutability of String in java
Immutability:
Now, going by the immutability, the String class has been designed so that the values in the common pool can be reused in other places/variables. This holds good if the String was created as
String a = "Hello World!";
However, if I create String like
String b = new String("Hello World!");
why is this immutable as well? (or is it?). Since this has a dedicated heap memory, I should be able to modify this without affecting any other variable. So by design, was there any other reason why String as a whole is considered immutable? Or is my above assumption wrong?
Second thing I wanted to ask was about the common string pool. If I create a string object as
String c = "";
is an empty entry created in the pool?
Is there any post already on these? If so, could someone share the link?
new String() is an expression that produces a String ... and a String is immutable, no matter how it is produced.
(Asking if new String() is mutable or not is nonsensical. It is program code, not a value. But I take it that that is not what you really meant.)
If I create a string object as String c = ""; is an empty entry created in the pool?
Yes; that is, an entry is created for the empty string. There is nothing special about an empty String.
(To be pedantic, the pool entry for "" gets created long before your code is executed. In fact, it is created when your code is loaded ... or possibly even earlier than that.)
So, I was wanted to know whether the new heap object is immutable as well, ...
Yes it is. But the immutability is a fundamental property of String objects. All String objects.
You see, the String API simply does not provide any methods for changing a String. So (apart from some dangerous and foolish1 tricks using reflection), you can't mutate a String.
and if so what was the purpose?.
The primary reason that Java String is designed as an immutable class is simplicity. It makes it easier to write correct programs, and read / reason about other people's code if the core string class provides an immutable interface.
An important second reason is that the immutability of String has fundamental implications for the Java security model. But I don't think this was a driver in the original language design ... in Java 1.0 and earlier.
Going by the answer, I gather that other references to the same variable is one of the reasons. Please let me know if I am right in understanding this.
No. It is more fundamental than that. Simply, all String objects are immutable. There is no complicated special case reasoning required to understand this. It just >>is<<.
For the record, if you want a mutable "string-like" object in Java, you can use StringBuilder or StringBuffer. But these are different types to String.
1 - The reason these tricks are (IMO) dangerous and foolish is that they affect the values of strings that are potentially shared by other parts of your application via the string pool. This can cause chaos ... in ways that the next guy maintaining your code has little chance of tracking down.
String is immutable irrespective of how it is instantiated
1) Short answer is yes, new String() is immutable too.
Because every possible mutable operation (like replace,toLowerCase etcetra) that you perform on String does not affect the original String instance and returns you a new instance.
You may check this in Javadoc for String. Each public method of String that is exposed returns a new String instance and does not alter the present instance on which you called the method.
This is very helpful in Multi-threaded environment as you don't have to think about mutability (someone will change the value) every time you pass or share the String around. String can easily be the most used data type, so the designers have blessed us all to not think about mutability everytime and saved us a lot of pain.
Immutability allowed String pool or caching
It is because of immutability property that the internal pool of string was possible, as when same String value is required at some other place then that immutable reference is returned. If String would have been mutable then it would not have been possible to share Strings like this to save memory.
String immutablity was not because of pooling, but immutability has more benefits attached to it.
String interning or pooling is an example of Flyweight Design pattern
2) Yes it will be interned like any other String as a blank String is also as much a String as other String instances.
References:
Immutability benefits of String
The Java libraries are heavily optimized around the constraint that any String object is immutable, regardless of how that object is constructed. Even if you create your b using new, other code that you pass that instance to will treat the value as immutable. This is an example of the Value Object pattern, and all of the advantages (thread-safety, no need to make private copies) apply.
The empty string "" is a legitimate String object just like anything else, it just happens to have no internal contents, and since all compile-time constant strings are interned, I'll virtually guarantee that some runtime library has already caused it to be added to the pool.
1) The immutable part isn't because of the pool; it just makes the pool possible in the first place. Strings are often passed as arguments to other functions or even shared with other threads; Making Strings immutable was a design decision to make reasoning in such situations easier. So yes - Strings in Java are always immutable, no matter how you create them (note that it's possible to have mutable strings in java - just not with the String class).
2) Yes. Probably. I'm not actually 100% sure, but that should be the case.
This isn't strictly an answer to your question, but if behind your question is a wish to have mutable strings that you can manipulate, you should check out the StringBuilder class, which implements many of the exact same methods that String has but also adds methods to change the current contents.
Once you've built your string in such a way that you're content with it, you simply call toString() on it in order to convert it to an ordinary String that you can pass to library routines and other functions that only take Strings.
Also, both StringBuilder and String implements the CharSequence interface, so if you want to write functions in your own code that can use both mutable and immutable strings, you can declare them to take any CharSequence object.
From the Java Oracle documentation:
Strings are constant; their values cannot be changed after they are
created.
And again:
String buffers support mutable strings. Because String
objects are immutable they can be shared.
Generally speaking: "all primitive" (or related) object are immutable (please, accept my lack of formalism).
Related post on Stack Overflow:
Immutability of Strings in Java
Is Java String immutable?
Is Java "pass-by-reference" or "pass-by-value"?
Is a Java string really immutable?
String is immutable. What exactly is the meaning?
what the reason behind making string immutable in java?
About the object pool: object pool is a java optimization which is NOT related to immutable as well.
String is immutable means that you cannot change the object itself no matter how you created it.And as for the second question: yes it will create an entry.
It's the other way around, actually.
[...] the String class has been designed so that the values in the common pool can be reused in other places/variables.
No, the String class is immutable so that you can safely reference an instance of it, without worrying about it being modified from another part of your program. This is why pooling is possible in the first place.
So, consider this:
// this string literal is interned and referenced by 'a'
String a = "Hello World!";
// creates a new instance by copying characters from 'a'
String b = new String(a);
Now, what happens if you simply create a reference to your newly created b variable?
// 'c' now points to the same instance as 'b'
String c = b;
Imagine that you pass c (or, more specifically, the object it is referencing) to a method on a different thread, and continue working with the same instance on your main thread. And now imagine what would happen if strings were mutable.
Why is this the case anyway?
If nothing else, it's because immutable objects make multithreading much simpler, and usually even faster. If you share a mutable object (that would be any stateful object, with mutable private/public fields or properties) between different threads, you need to take special care to ensure synchronized access (mutexes, semaphores). Even with this, you need special care to ensure atomicity in all your operations. Multithreading is hard.
Regarding the performance implications, note that quite often copying the entire string into a new instance, in order to change even a single character, is actually faster than inducing an expensive context switch due to synchronization constructs needed to ensure thread-safe access. And as you've mentioned, immutability also offers interning possibilities, which means it can actually help reduce memory usage.
It's generally a pretty good idea to make as much stuff immutable as your can.
1) Immutability: String will be immutable if you create it using new or other way for security reasons
2) Yes there will be a empty entry in the string pool.
You can better understand the concept using the code
String s1 = new String("Test");
String s2 = new String("Test");
String s3 = "Test";
String s4 = "Test";
System.out.println(s1==s2);//false
System.out.println(s1==s3);//false
System.out.println(s2==s3);//false
System.out.println(s4==s3);//true
Hope this will help your query. You can always check the source code for String class in case of better understanding Link : http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java
1-String is immutable.See this:
Is a Java string really immutable?
So you can create it with many way.
2-Short answer: Yes will be empty.
Strings created will always be immutable regardless of how they are created.
Answers to your questions:
The only difference is:
When string is created like -- {String a = "Hello World!";} then only one object gets created.
And when it is created like -- {String b = new String("Hello World!");} then two objects get created. The first one, because you have used 'new' keyword and the second one because of the String property.
Yes, for sure. There will be an empty entry created in the pool.
String is immutable because it does not provide you with a mean to modify it. It is design to avoid any tampering (it is final, the underlying array is not supposed to be touched ...).
Identically, Integer is immutable, because there is no way to modify it.
It does not matter how you create it.
Immutability is not a feature of new, it is a feature of the class String. It has no mutator methods, so it immutable.
String A = "Test"
String B = "Test"
Now String B called"Test".toUpperCase()which change the same object into"TEST", soAwill also be"TEST"` which is not desirable.
Note that in your example, the reference is changed and not the object it refers to, i.e. b as a reference may be changed and refer to a new object. But that new object is immutable, which means its contents will not be changed "after" calling the constructor.
You can change a string using b=b+"x"; or b=new String(b);, and the content of variable a seem to change, but don't confuse immutability of a reference (here variable b) and the object it is referring to (think of pointers in C). The object that the reference is pointing to will remain unchanged after its creation.
If you need to change a string by changing the contents of the object (instead of changing the reference), you can use StringBuffer, which is a mutable version of String.
I read a lot that string objects are immutable and only string buffers are mutable. But When I tried this program. I am confused. So whats going on here in this program.
class Stringss {
public static void main(String[] args) {
String s="hello";
String ss=new String("xyz");
System.out.println(ss);
System.out.println(s);
s="do";
ss=new String("hello");
System.out.println(s);
System.out.println(ss);
}
}
Output is
xyz
hello
do
hello
In your code, s is not a String object. It's a reference to a String object. Your code makes it reference several different String objects. But the String object itself doesn't change.
A String would not be immutable if you could do, for example
s.setCharacterAt(3, 'Z');
or
s.setValue("foo")
But doing
s = "a string";
s = "another string";
Doesn't change what the "a string" object contains. It just makes s point to another String.
To make an analogy, a VHS is mutable. You can replace what is on the band. A DVD is immutable: you can't change what's being written on the disk. But that doesn't prevent the DVD player to play several different DVDs. Putting another DVD inside the DVD player doesn't change what the DVDs contain.
It means that whenever you need to edit a String, it creates a brand new String object instead of amending the original.
I think you are confused by the difference between the reference to the String object and the String object itself.
When you say
String myString = "Hello";
the runtime creates an object in memory "Hello." You can't directly mess with the way this object is stored because Java manages memory. But you still need to be able to make use of that object, so the reference myString lets you do that in an indirect way.
When you make calls on myString with the . operator like these:
myString.charAt(0)
myString.length
You are using your reference to get some information about that string, but you never touch the string itself.
Now it gets a little tricky. If you do this next:
myString = "Later";
The runtime creates a new object in memory "Later," and myString points to that now instead. "Hello" is still sitting in memory, but you have no way to get information from it anymore. Eventually, Java will figure that out and clean it up so you get that memory back for other things. This shows the reference can point to anything, and those things can change all the time.
Now let's say I want to change the string itself like this:
myString = myString + ", dude.";
It looks like you are modifying myString to add more stuff to it, but you actually aren't. You have the original object in memory ("Later"), and the runtime creates a second object in memory (", dude."). Then the runtime creates a third object that represents the combination of the two: "Later, dude."
If Strings were mutable (like StringBuffer and StringBuilder), you could have one object and just keep changing it. But they are not, so every time you think you're just modifying it, you are creating new ones. This can lead to a lot of wasted memory and then a decline in performance when the runtime tries to get it all back.
So it is about the difference between reference and object.
Hope that helps.
String is immutable means you can not modify the String object
the above three ways are same, String is not a primitive data type, its a class
One way to understand it may be by doing this:
public static void main(String[] args) {
String s="hello";
tryToMutateString(s);
System.out.println(s); //Will just print "hello" since our s still refers to that
}
public static void tryToMutateString(String given) {
given += "mutated"; //Creates a new String, the string that given pointed to earlier won't change
}
If I write this code :
String s = new String("TestString");
I understand how s refers to a string created dynamically. s is not an object in itself, but refers to one.
But I am not able to figure out what this means :
String s = "TestString";
Q1. If it would have been some primitive data type I would understand, but what does this signify for a class type ?
Q2. Is this kind of initialization allowed for user created classes as well ?
Java Level : Beginner
Q1. If it would have been some primitive data type I would understand, but what does this signify for a class type ?
In this case, "TestString" is a string literal. A string literal also serves as a reference to an instance of String. This is per the language specification, §3.10.5. So, in your particular case "TestString" is a reference to an instance of String, and you are assigning that same reference to your variable s.
Now, there are some rather special things about Strings that are referred to by literals. Two string literals with the same value (logically, as strings) always refer to the same instance of String. This is due to the "interning" of string literals.
However, when you say
String s = new String("TestString");
it is still the case that "TestString" refers to an instance of String, in fact to an instance in the string intern pool, but it is not the case that s refers to this same string. Instead, s is initialized to have its value equal to "TestString", but it is in fact a new reference. That is:
String s = new String("TestString");
String t = "TestString";
System.out.println(s == t);
This will print false.
Q2. Is this kind of initialization allowed for user created classes as well ?
No.
String s = "TestString";
Is the normal way to create a String. In fact when you do:
String s = new String("TestString");
What you're doing is create a string first, then passing it as an argument to new String(); So the question is not why the first one exists, but why the second one does. The answer is pretty subtle and you probably won't ever care: The first way creates a String literal that doesn't get garbage collected, and is shared on all the VM. The second one, instead, does. This means, for performance reasons, there are cases when you want to use the second form, like when working with very very large strings.
You can read more about it here:
http://kjetilod.blogspot.com.es/2008/09/string-constructor-considered-useless.html
From the Oracle Documentation:
The most direct way to create a string is to write:
String greeting = "Hello world!";
In this case, "Hello world!" is a string literal—a series of
characters in your code that is enclosed in double quotes. Whenever it
encounters a string literal in your code, the compiler creates a
String object with its value—in this case, Hello world!.
As with any other object, you can create String objects by using the
new keyword and a constructor.
Q1. If it would have been some primitive data type I would understand,
but what does this signify for a class type ?
No, this is special case, in case of String literals, String s = "someString" statement means we are referring to someString which is stored in string constant pool. someString will be an instance of String class but will be stored in string literal pool.
The special thing about String literal pool will be.
String s = "someString";
String s1 = "someString";
Here, s == s1' will returntrue` as they will refer to the same object in string literal pool.
String s2 = new String("someString");
String s3 = new String("someString");
Here, s2 == s3 will return false as both string will be created in non-constant pool memory.
You can find a good tutorial regarding strings here
http://www.thejavageek.com/2013/06/19/the-string-constant-pool/
http://www.thejavageek.com/2013/06/17/string-immutability-in-java/
Q2. Is this kind of initialization allowed for user created classes as
well ?
No we can't.
String s1 = new String("string");
String s2 = new String("string");
String s3 = "string";
String s4 = "string";
System.out.println(s1 == s2); //FALSE
System.out.println(s2.equals(s1)); //TRUE
System.out.println(s3 == s4); //TRUE
System.out.println(s3.equals(s4)); //TRUE
What is the difference between creation of s1 and s3 ?
Please let me know
In String we are having only String object then why it treats this two differently.
s1 and s2 are having different memory address while s3 and s4 has same memory address.
why it works based on new operator.?
The String objects that represent string literals in your Java source code are added to a shared String pool when the classes that defines them are loaded1. This ensures that all "copies" of a String literal are actually the same object ... even if the literal appears in multiple classes. That is why s3 == s4 is true.
By contrast, when you new a String, a distinct new String object is created. That is why s1 == s2 is false. (This is a fundamental property of new. It is guaranteed to create and return a new object ... if it completes normally.)
However, in either case, the strings will have the same characters, and that is why equals is returning true.
While it is important to understand what is going on, the real lesson is that the correct way to compare Java strings is to use equals and not ==.
If you want to arrange that your String objects can be tested for equality using ==, you can "intern" them using the String.intern method. However, you have to do this consistently ... and interning is an expensive process in various respects ... so it is generally not a good idea.
1 - Actually, it is a bit more complicated than that. They objects get added to the pool at some time between class loading and first use of the literals. The precise timing is unspecified and JVM implementation dependent. However it is guaranteed to happen just once, and before any application code sees the String object reference corresponding to the literal.
s1 is a new String object that does not belong to a part of any pooled instance. s3 is an instance of a string that comes from a pool. Lookup java String pool. Take a look at the related intern() method on String.
The concept is not unique to java. String interning is supported in other languages. On that related note, pooling frequently used objects follows the flyweight pattern and is not limited to Strings. Take a look at Integer.valueOf(). Integers have a constant pool of their own too.
The JVM has an automatic optimisation. Unless you specifically create a new String object, and another String object already exists with the same value, the JVM automatically assumes that a new object is not a necessity, and will assign you a pointer to the equal String object that already exists.
Essentially, when you use the second option, this is what happens:
Step 1
First Object is created no problem.
Step 2
Before the second object is created, the String pool is checked for a value.
If that value currently exists, then there is no need to create a new object. It just returns the reference to the String object.
Step 3
Instead of being assigned a new Object, it is simply given a reference to the object made in step 1. This is to save memory.
This happens because the new operator forces creation of a new instance of String, while in the second case, as String is an immutable class, the JVM provides you with the same String instance for both variables to save memory. As there is no chance one of such objects will change causing the second one change as well (immutable, remember?) this is OK.
I have an assert statement to check the equal method in a class. below is the 2 statements
Assert.assertTrue(a.equals(new VideoObj(title, year, director)));
Assert.assertTrue(a.equals(new VideoObj(new String(title), year, director)));
what is the difference in the two statements? and why does the 2nd assert statement have new String(title), can someone tell me what is the difference in doing so?
And also could you provide with a tutorial for me to learn writing test class for Java?
thanks
new String() explicitly creates a new object of String.
And:
Assert.assertTrue(a.equals(new VideoObj(title, year, director)));
reuses existing String object (which can give you different results depending on equals method implementation in VideoObj), or uses some other object like byte[] as there is a constructor for new String(byte[]). Of course there are many others (see Java API).
...edit
Check this out:
String s1=new String("abcxyz");
String s2=new String("abc"+"xyz");
String s3=s1+s2;
String s4="abcxyz"; // string literal will go to string pool
String s5="abc"+"xyz"; // string literal will go to string pool
System.out.println(s1==s2);
System.out.println(s2==s3);
System.out.println(s3==s4);
System.out.println(s4==s5); // TRUE (the rest are false)
System.out.println(s2==s4);
System.out.println(s2==s5);
System.out.println(s3==s1);
System.out.println(s3==s5);
The new String() statement creates a new String object with the content of the original String. That gives you two String objects (the original one and the one that was newly created with the new String(originalString) statement) that have equal content, but are two different Java objects. If you compare these two objects with the == operator, this comparison will return false, because it's two different objects. Whereas a comparison with the String's equals() method will still return true, because these two strings have the same text stored inside them.
So I assume the intention of this assertion in the test is to make sure that the equals() method of "a" really uses the equals() method of the title string to check for equality, and does not just do a simple == comparison of the two title strings. Without that assertion, such an invalid implementation of a's equals() method could remain unnoticed because the two title strings in the compared object could be references to the same String object, which would then also give you the expected result when using the (wrong) == operator to test them for equality.
The difference is this:
If in VideoObj's the equals() method has been overridden and is using the String that is passed in via the constructor as title, it's checking to make sure it works if the String isn't a literal
If in equals() someone did this:
...
if (otherObj.getTitle() == this.title) {
...
The first assertion would succeed while the second would fail if title was a string literal. String literals in Java are interned into a pool meaning that you end up with multiple references to the same literal if it's used multiple times;
String a = "This is a string";
String b = "This is a string";
// a and b will both be the same reference
String c = new String("This is a string");
// c will *not* be the same reference
Edit: Note this is assuming that title in your first assertion is indeed a String
If title is not a String, then the second assert statement might be invoking a different VideoObj constructor. Without more info about title and about the VideoObj class, it's hard to say more.
Do a web search for junit tutorial to get lots of resources for learning how to write test classes.
EDIT From your comment to the answer by #BrianRoach, I gather that your VideoObj.equals(Object) method is implemented as follows:
public boolean equals(Object thatObject) {
if (!(thatObject instanceof VideoObj)) return false;
VideoObj that = (VideoObj) thatObject;
return ((_title.equals(that.title()))
|| (_director.equals(that.director()))
|| (_year == that.year()));
}
If that's right, then the problem is that your return statement should be using && instead of || operators. That would explain why your asserts are not complaining.
Java does some optimization. If you have two strings with the same value it is most probably the same object. This can be done because strings are immutable. But if you explicitly create a new String with a constructor call, a new object is created.
There should be no difference between the 2 statements, provided that 'title' is a String.
title can either be a String, a StringBuffer, a StringBuilder, a char[] or a byte[]. If it's a String, it'll run the same constructor as the other call, but in all other cases it may run a totally different, overloaded, constructor.
Without seeing the type of title, it's impossible to tell which.
Edit: Since the type is String, the reason for the new String is most likely to make sure that the underlying code does not compare strings using == (reference-equals) by mistake. If it did, the first test may pass (string constants with the same value may indeed reference the same String object and the test may use constants for setup and test) while the second one would break since == would no longer match with a freshly created String.