tags:

views:

115

answers:

6

Hi there!

I am writing an app for J2ME devices and pretty much care about unnecessary String creation. As working with Strings is built-in, i.e. it is not necessary to create them explicitly, I am not sure if I understand it right.

For instance returning a String (just by using the double quotes) creates the string when it is being returned, i.e. if I have several return statements returning different Strings, only one of the would be created. Is that right?

Also when using Strings for printing messages with Exceptions, these Strings never get created, if the Exception doesn't get thrown, right?

Sorry to bother you with such a newbie question.

A: 

Strings (and other objects) only get created when you call them.

So to answer your questions:

  1. Yes, only the String that gets returned will get created
  2. Yes, only when the exception is thrown, this String will get created
Molske
+1  A: 
  1. Right
  2. Right
Gopi
+3  A: 

I'm not at all sure about the answers you've received so far. If you're just returning a string literal, e.g.

return "foo";

then those values are embedded into the class file. The JVM makes sure that only one instance of that string is ever created (from the literal) - but I don't think there's any guarantee that it won't create strings for all the constants in a class when the class itself is loaded.

Then again, because the string will only be created once (per string constant) it's unlikely to be an issue.

Now, if your code is actually more like this:

return "foo" + new Date();

then that is dynamically creating a string - but it will only be created if the return statement is actually hit.

Jon Skeet
It says at `String#intern': *All literal strings and string-valued constant expressions are interned.*. So a String, that is based on a literal is created once and at least when the first expression using that literal is executed. I doubt that the classloader will look at the constant pool and create String instances for all literals proactivly. But you never know ;)
Andreas_D
@Andreas_D: It would make life a lot easier if it did, I'd say.
Jon Skeet
Thanks Jon! You're always very practical and helpful!
Albus Dumbledore
Andreas, would you explain to me what you mean by saying "I doubt that the classloader will look at the constant pool and create String instances for all literals proactivly."?
Albus Dumbledore
@Jon - Just looked at the [JVM spec](http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#19124), and to my surprise and your reassurance: *Loading of a class or interface that contains a String literal may create a new String object (§2.4.8) to represent that literal. This may not occur if the a String object has already been created [...]*
Andreas_D
If I've interpreted it correctly, [the specification](http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#22972) suggests that the class' constant pool (and by association the string literals) is created when the class is created by the class loader, so I imagine this would typically result in the majority of said strings being created during startup? I may be way off base with that conclusion, though.
Tim Stone
@Tim - it is my understanding that it does create the Strings at class load time. However, it possible that JVM / classloader avoid creating String objects for Strings that are already in the string pool ... unlike what has to happen when you call `String.intern()` from application code.
Stephen C
+1  A: 
Andreas_D
I begin to suspect that all Strings are interned unless _specially_ declared that are not. So it seems that creating a String instance by a String literal is the same as creating an object, implementing the Flyweight pattern.
Albus Dumbledore
@Albus - Well, it's important not to fall into traps, though. Java interning is done with compile-time guarantees in mind, so iterative string creation *based* on literals (e.g. imaginary method `repeat("*", 5)`) doesn't gain any benefit from automatic interning (which you probably know now). It's more of a best-efforts operation on the part of the JVM, using the available up-front information. On a side note, thanks for the interesting question, it made me consider something I want to go experiment with now.
Tim Stone
+2  A: 

The answer is a bit more complicated than some of the other answers suggest.

  • The String value that corresponds to a String literal in your source code gets created once, when the class is loaded. Furthermore, these Strings are automatically "interned", which means that if the same literal appears at more than one place in any class, only one copy of the String will be kept. (Any other copies, if they were created will get garbage collected.)

  • When the application calls new String(...), when it evaluates a String concatenation expression (i.e. the + operator), or when it calls one of the many library methods that create Strings under the hood, a new String will be created.

So to answer your questions:

1 - The following will not actually create a String at all. Rather it will return a String that was created when the class was loaded:

        return "some string";

2 - The following will create two Strings. First it will call someObject.toString(), then it will concatenate that with the literal to give another String.

        return "The answer is :" + someObject;

3 - The following will not create a String; see 1.

        throw new Exception("Some message");

4 - The following will create two Strings when it is executed; see 2.

        throw new Exception(someObject + "is wrong");

(Actually, 3 and 4 gloss over the fact that creating an exception causes details of the current thread's call stack to be captured, and those details include a method name, class name and file name for each frame. It is not specified when the Strings that represent these things actually get created, or whether they are interned. So it is possible that the act of creating an Exception object triggers creation of a number of Strings.)

Stephen C
Are you actually sure of 1? I mean, the others seem to be saying that returning a String literal was the same as invoking the constructor on a String object, with the difference that it was automatically pooled, so why should it be created at class-loading time?
Albus Dumbledore
@Albus - I am **sure** of this. This also agrees with what @Jon Skeet says ... so it must be right :-)
Stephen C
I second Stephen's conclusion (and faith in Jon Skeet). :P
Tim Stone
A: 

The main concept here is that the heap allocation(what you say creation) for any String or in more general terms for any object doesn't take place until your logic-flow makes the interpreter executes that line of compiled code.

off-hook