tags:

views:

859

answers:

6

While looking at online code samples, I have sometimes come across an assignment of a String constant to a String object via the use of the new operator.

For example:

String s;
...
s = new String("Hello World");

This, of course, compared to

s = "Hello World";

I'm not familiar with this syntax and have no idea what the purpose or effect would be. Since String constants typically get stored in the constant pool and then in whatever representation the JVM has for dealing with String constants, would anything even be allocated on the heap?

+6  A: 

Take a look at this blog post.

http://kjetilod.blogspot.com/2008/09/string-constructor-considered-useless.html

Ruggs
Jeez, I wasn't aware of the fact that substring doesn't return a completely different object. That's bizarre. thanks!
Uri
Bizarre and very dependent on the implementation. It is interesting but may be dangerous.
OscarRyz
Uri: Read through entire String class, it's enlightening. Substring is actually a constant-time operation! :)
Esko
A: 

Generally, this indicates someone who isn't comfortable with the new-fashioned C++ style of declaring when initialized.

Back in the C days, it wasn't considered good form to define auto variables in an inner scope; C++ eliminated the parser restriction, and Java extended that.

So you see code that has

int q;
for(q=0;q<MAX;q++){
    String s;
    int ix;
    // other stuff
    s = new String("Hello, there!");
    // do something with s
}

In the extreme case, all the declarations may be at the top of a function, and not in enclosed scopes like the for loop here.

IN general, though, the effect of this is to cause a String ctor to be called once, and the resulting String thrown away. (The desire to avoid this is just what led Stroustrup to allow declarations anywhere in the code.) So you are correct that it's unnecessary and bad style at best, and possibly actually bad.

Charlie Martin
Either I completely don't understand this, or it's not related to the actual question. The question is about the difference between ...="Hello" and ...=new String("Hello"). You seem to be talking about the difference between "String s=..." and "String s; ...; s=...".
Dave Costa
A: 

I guess it will depend on the code samples you're seeing.

Most of the times using the class constructor "new String()" in code sample are only to show a very well know java class instead of creating a new one.

You should avoid using it most of the times. Not only because string literals are interned but mainly because string are inmutable. It doesn't make sense have two copies that represent the same object.

While the article mensioned by Ruggs is "interesting" it should not be used unless very specific circumstances, because it could create more damage than good. You'll be coding to an implementation rather than an specification and the same code could not run the same for instance in JRockit, IBM VM, or other.

OscarRyz
It makes sense to have two copies if you want to throw away one of them, and it's a lot bigger than the other...
Jon Skeet
If one is bigger than the other, they would be two different objects in first place isn't? :-/
OscarRyz
+1  A: 

The only time I have found this useful is in declaring lock variables:

private final String lock = new String("Database lock");

....

synchronized(lock)
{
    // do something
}

In this case, debugging tools like Eclipse will show the string when listing what locks a thread currently holds or is waiting for. You have to use "new String", i.e. allocate a new String object, because otherwise a shared string literal could possibly be locked in some other unrelated code.

Dave Ray
I think it's better to have use `private static class Lock {}; private final Lock lock = new Lock();`, as the class name shows up pretty much everywhere. However, it will cost you a couple of K, because HotSPot isn't that efficient.
Tom Hawtin - tackline
I can buy that. Maybe I'll give it a try next time.
Dave Ray
Object lock = new Object() does the same at all ;-)
Hardcoded
+1  A: 

Well, that depends on what the "..." is in the example. If it's a StringBuffer, for example, or a byte array, or something, you'll get a String constructed from the data you're passing.

But if it's just another String, as in new String("Hello World!"), then it should be replaced by simply "Hello World!", in all cases. Strings are immutable, so cloning one serves no purpose -- it's just more verbose and less efficient to create a new String object just to serve as a duplicate of an existing String (whether it be a literal or another String variable you already have).

In fact, Effective Java (which I highly recommend) uses exactly this as one of its examples of "Avoid creating unnecessary objects":


As an extreme example of what not to do, consider this statement:

String s = new String("stringette");  **//DON'T DO THIS!**


(Effective Java, Second Edition)

Vineet
Just because you use the overload containing a string doesn't mean it's pointless - see Software Monkey's answer.
Jon Skeet
+23  A: 

The one place where you may need new String(String) is to force a substring to copy to a new underlying character array, as in

small=new String(huge.substring(10,20))

However, this behavior is unfortunately undocumented and implementation dependent.

I have been burned by this when reading large files (some up to 20 MiB) into a String and carving it into lines after the fact. I ended up with all the strings for the lines referencing the char[] consisting of entire file. Unfortunately, that unintentionally kept a reference to the entire array for the few lines I held on to for a longer time than processing the file - I was forced to use new String() to work around it.

The only implementation agnostic way to do this is:

small=new String(huge.substring(10,20).toCharArray());

This unfortunately must copy the array twice, once for toCharArray() and once in the String constructor.

There needs to be a documented way to get a new String by copying the chars of an existing one; or the documentation of String(String) needs to be improved to make it more explicit (there is an implication there, but it's rather vague and open to interpretation).

Software Monkey
"However, this behavior is unfortunately undocumented and implementation dependent." JavaDoc for the `String(String)` constructor says "Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string. Unless an explicit copy of original is needed, use of this constructor is unnecessary since Strings are immutable. " which is a roundabout way of saying said constructor makes an explicit copy of the underying `char[]` of `String` passed to it.
R. Bemrose
@R. Bemrose. No, that's what it *could* imply. What it states is that you will get a new copy of the *String* object - it makes no statement about the constituent contents of said object. A new String sharing the underlying array is still a new String and a copy of the old one. Contrast that to `String(char[] value)`, where it explicitly states: The contents of the character array are copied.
Software Monkey