Why should I not instantiate a string object with a constructor? - java

In Java, apparently, String s = "foo" is preferred over String s = new String("foo").
Why? Isn't a new string object created in both cases? Why would the first case preclude calling a constructor?

Why?
Because the second approach results in two string objects (the original due to the string literal, plus an explicit copy).

The first case is a string literal, simply a shorthand the language offers you to create a string. The String class constructor still gets called, just not explicitly, which means less typing and less code clutter.
The second case takes the String object already created by the literal and passes it to a constructor, which copies the content to create a new, separate String object. The literal will still be around because literals are interned.
There is rarely a point to using the String constructor (pretty much only when you've created a substring of a very large string and want to release the memory used by the rest of the string, because substrings by default use the same underlying char array as the original string, just with a different offset and length.

I don't think it's preferable. I assume the only "benefit" you get is that if you wrongfully use the "==" operator rather than the equals method, have two different instances of a string will fail faster which will prompt you to fix your code. (the == operator may "succeed" and fail unpredictably)
Unless of course your code requires you to construct two different instances for whatever reason

Why? Isn't a new string object created in both cases?
No, the initial form being a string literal will be interned such that only one instance is created:
String s = "foo";
String s2 = "foo";
s == s2 => true

Related

Particularities of strings vs other objects

I'm into Java since a short time, and I was wondering: Strings are in fact objects, but I heard that in assigning them a value and retrieving it they act quite differently, almost as if they were primitive types... could someone make it more clear?
What do I exactly have to care about when I declare/edit/access a string compared to other objects?
First of all Java has string literals. That means you may write String foo = "bar";.
String are immutible (once you create one, you can't change it) and it helps JVM to do one trick called "string pool". String literals are stored in pools, and in the following example both foo and bar may point to one instance of string. String foo = "baz"; String bar = "baz". You may even compare them with ==, but you should never do that. How ever, equals() method (which you use to compare strings in Java) may benefit from it since it does not need to compare strings if both vars point to the same string.
Please check this topic for more info What is the Java string pool and how is "s" different from new String("s")?

How should I copy Strings in Java?

String s = "hello";
String backup_of_s = s;
s = "bye";
At this point, the backup variable still contains the original value "hello" (this is because of String's immutability right?).
But is it really safe to copy Strings with this method (which is of course not safe to copy regular mutable objects), or is better to write this? :
String s = "hello";
String backup_of_s = new String(s);
s = "bye";
In other words, what's the difference (if any) between these two snippets?
EDIT - the reason why the first snippet is safe:
Let me just explain things with a little more detail, based on the good answers already provided (which were essentially focused on the question of difference of performance between the 2 snippets):
Strings are immutable in Java, which means that a String object cannot be modified after its construction.
Hence,
String s = "hello"; creates a new String instance and assigns its address to s (s being a reference to the instance/object)
String backup_of_s = s; creates a new variable backup_of_s and initializes it so that it references the object currently referenced by s.
Note: String immutability guarantees that this object will not be modified: our backup is safe
Note 2: Java garbage collection mechanism guarantees that this object will not be destroyed as long as it is referenced by at least one variable (backup_of_s in this case)
Finally, s = "bye"; creates another String instance (because of immutability, it's the only way), and modifies the s variable so that it now references the new object.
Since strings are immutable, both versions are safe. The latter, however, is less efficient (it creates an extra object and in some cases copies the character data).
With this in mind, the first version should be preferred.
Strings are immutable objects so you can copy them just coping the reference to them, because the object referenced can't change ...
So you can copy as in your first example without any problem :
String s = "hello";
String backup_of_s = s;
s = "bye";
Your second version is less efficient because it creates an extra string object when there is simply no need to do so.
Immutability means that your first version behaves the way you expect and is thus the approach to be preferred.
Second case is also inefficient in terms of String pool, you have to explicitly call intern() on return reference to make it intern.
String str1="this is a string";
String str2=str1.clone();
How about copy like this?
I think to get a new copy is better, so that the data of str1 won't be affected when str2 is reference and modified in futher action.

Why to create a String object using new [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java Strings: “String s = new String(”silly“);”
What is the purpose of the expression “new String(…)” in Java?
There are two ways to create a String object:
1) using literal as in String s ="hello" (creates one object)
2) using new as in String s = new String("hello") (creates two objects)
I was wondering why do ever I need to go for 2) approach?
If you create a string with new, then you get a different String reference. This can avoid creepy behaviour:
String s = "hello";
String t = "hello";
String u = new String("hello");
System.out.println(s==t);
System.out.println(t==u);
prints true, false. I can't really think of a real bit of software where I'd use this. But in a sense it is 'safer' to create new references, so that == doesn't surprise us.
The basic difference between them is memory allocation.
First option i.e
String s1 = "hello";
When you use this s1 is called as a string literal and memory for s1 is allocated at compile time.
But in 2nd case
String s2 = new String("hello");
In this case s2 is called as an object of String representing hello
When you tries to create two string literal using the first case, only one memory is referenced by those two literals. I mean String literals are working with a concept of string pool. when you create a 2nd string literal with same content, instead of allocating a new space compiler will return the same reference. Hence you will get true when you compare those two literals using == operator.
But in the 2nd case each time JVM will create a new object for each. and you have to compare their contents using equals() method but not with == operator.
If you want to create a new string object using 2nd case and also you don't want a new object, then you can use intern() method to get the same object.
String s = "hello";
String s1 = new String("hello").intern();
System.out.println(s == s1);
In this case instead of creating a new object, JVM will return the same reference s. So the output will be true
The only mentally sane occasion where new String("foo") should be used are unit-tests. You can make sure that the code does not use == for string comparisons but the proper .equals() method.
The second approach is just a possibility. Actually is never used (by most of developers). The first one is a less and more convenient version of the latter, no reasons to use the second way.
PS. The second just creates a different link to the literal. Technically they will re-use the same char array. The only difference is the reference will be different (i.e. == will give false, but NEVER use == for string comparison).
This can be understood as a constructor per copy. They are very used in C++. The net effect is having a duplicate of the object passed as a parameter, in this case, a String.

String initialization difference

Firstly apologies if this a very basic question, I'm just curious to know the difference between the following string definitions
String x= "hello";
String y = new String("hello");
I knew that in java String is a Class its neither a primitive nor a Wrapper(Correct me if this a misconception). Consider a class A, I've seen the following declarations for any class so far. i think A c; is valid and A a = new A(); is also valid. I'm confused with A a ="xyz"; this is how we declared a String as in above first type of definition. I'm sure that the above two definitions are absolutely different, like if i say x==y it returns false. I understand that y is the reference to the String object. What is x there, how is it stored in memory, interestingly i found that both x and y can access all the methods of String class.
Then what is the advantage of one over other.Can i know the applicability of each.
From the 2nd edition of Joshua Bloch's "Effective Java":
String s = new String("stringette");// DON'T DO THIS!
The statement creates a new String instance each time it is executed,
and none of those object creations is necessary. The argument to the
String constructor ("stringette") is itself a String instance,
functionally identical to all of the objects created by the
constructor. If this usage occurs in a loop or in a frequently invoked
method, millions of String instances can be created needlessly. The
improved version is simply the following:
String s = "stringette";
The first couple of answers you got are incorrect. There is a difference between the two statements. But first, the TL;DR version: Use String x = "hello"; in 99.99999% of situations.
The full answer:
The chief difference between those two is that in the first case, the string is implicitly interned; in the second case, it is not. This is a very real difference, although it only comes into play in select situations. So in the first case, if you have any other strings with the same series of characters ("hello"), your x will refer to the one shared object that is used in all of those places (this is useful, since String instances are immutable). In the second case, you're explicitly saying you need (for whatever reason) to have a String instance with that sequence of characters which is separate from any others. There are very, very few reasons to do that.
With regard to x==y, in Java you compare strings for equality using equals, not ==. The == operator when used with object references compares the references (e.g., do both variables point to the same object), not the object contents.
So: Prefer the first form to the second unless you have a good reason for doing the second.
String a = "hello"; //this kind of declaration always return "singlton" instance.
String b = "hello";
String c = new String("hello"); //This kind of declaration always return a new instance.
SO
a ==b;
but
a !=c
Very simply, the value of x is a String. A normal java.lang.String.
You're used to the idea that there are literals for primitive types (like, 7, or 3.14159, or true, or 'q'), but it seems what you may not have realised is that there are literal forms for some object types too. The only ones i can think of are java.lang.String, where you can write "hello", and java.lang.Class, where you can write SomeClass.class.
I understand that y is the reference to the String object. What is x there[...]?
Both x and y are references to String objects. The x is a reference to an interned string (as T.J. Crowder already wrote in his answer), the y is a reference to a second String object with the same content. This means:
x == y --> false
x.equals(y) --> true
y.equals(x) --> true
Then what is the advantage of one over other.Can i know the applicability of each.
Always use the first, direct version. The only valid exception which I ever encountered and found to be valid is test code which explicitly want to make sure, that the code to be tested does not use == for string comparisons but uses the proper x.equals(y) method.
One more way to initialize String is
String str =("abc");
It seems at first that this would give an error (because of the brackets) but this doesn't. Surprisingly.

what is the advantage of string object as compared to string literal

i want to know where to use string object(in which scenario in my java code).
ok i understood the diff btwn string literal and string object, but i want to know that since java has given us the power to make string object, there must be some reason, at some point string object creation would be useful. so i want to know in which scenario can we prefer string object in place of string literal.
In most situations, you should use String literals to avoid creating unnecessary objects. This is actually Item 5: Avoid creating unnecessary objects of Effective Java:
Item 5: Avoid creating unnecessary objects
It is often appropriate to reuse a
single object instead of creating a
new functionally equivalent object
each time it is needed. Reuse can be
both faster and more stylish. An
object can always be reused if it is
immutable (Item 15). As an extreme
example of what not to do, consider
this statement:
String s = new String("stringette"); // DON'T DO THIS!
The statement creates a new String
instance each time it is executed, and
none of those object creations is
necessary. The argument to the String
constructor ("stringette") is itself a
String instance, functionally
identical to all of the objects
created by the constructor. If this
usage occurs in a loop or in a
frequently invoked method, millions of
String instances can be created
needlessly. The improved version is
simply the following:
String s = "stringette";
This version uses a single String
instance, rather than creating a new
one each time it is executed.
Furthermore, it is guaranteed that the
object will be reused by any other
code running in the same virtual
machine that happens to con- tain the
same string literal [JLS, 3.10.5]
There is however one situation where you want to use the new String(String) constructor: when you want to force a substring to copy to a new underlying character array like in:
String tiny = new String(huge.substring(0, 10));
This will allow the big underlying char[] from the original huge String to be recycled by the GC.
Don't use a new String object if you know what the string is. For example:
String str = new String("foo"); // don't do this
You are thus creating an unnecessary object - once you have a String object created from the literal, and then you create another one, taking the first one as constructor argument.
Contrary to your question, there is a DISADVANTAGE of using a String object compared to String literal.
When you declare a String literal, String s = "foo", the compiler will check for an existing "foo" object on the heap and assign 's' to already existing "foo".
However, if you create a String object, String s = new String("foo"), an entirely new object will be created on the heap (even if there is already an existing "foo"). Strings being immutable this is totally unnecessary.
Here is good reference: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html
String a = "ABC";
String b = new String("ABC");
String c = "ABC";
a == b // false
a == c // true
a.equals(b) // true
a.equals(c) // true
The point is that a & c point to the same "ABC" object (JVM magic). Using "new String" creates a new object each time. IMO, using string object is a disadvantage, not an advantage. However, as another poster said, string object is useful for converting byte[], char[], StringBuffer - if you need to do that.
String literals are converted to String objects, and as others pointed out, creating explicit String objects is unnecessary and inperformant, as it defeats String pooling.
However, there is one situation where you want to create new Strings explicitly: If you use just a small part of a very long String. String.substring() prevents the original String from getting GC'd, so you can save memory when you write
String s = new String(veryLongString.substring(1,3));
instead of
String s = veryLongString.substring(1,3);
literal strings are objects created in a String Pool and if they have the same value, they are referencing to the same object.
System.out.println("abc"=="abc"); // the output is true
Meanwhile, string object are real objects in memory and if they have the same value, there's no guarantee that they are referencing to the same object.
String a = new String("abc");
String b = new String("abc");
System.out.println(a==b); // the output is false

Categories

Resources