views:

400

answers:

5

1.

static final String memFriendly = "Efficiently stored String";
System.out.println(memFriendly);

2.

System.out.println("Efficiently stored String");

Will Java compiler treat both (1 and 2) of these in the same manner?

FYI: By efficiently I am referring to runtime memory utilization as well as code execution time. e.g. can the 1st case take more time on stack loading the variable memFriendly?

+2  A: 

Yes.

OK, I need at least 15 characters in my answer.

skaffman
I believe so too but I couldn't find a concrete reference to it, I mean theoretically. Thanks
Monis Iqbal
+1  A: 

In this case, the compiler will handle both the same.

Anytime a String is defined at compile time, Java will optimize the storage of Strings.

If a string is defined at runtime, Java has no way of doing the same optomization.

jjnguy
I believe so too but I couldn't find a concrete reference to it, I mean theoretically. ThanksThis is a good article with references but not what I am looking for:http://muzso.hu/2009/03/05/strange-behaviour-in-java-compilers-string-concatenation-caused-by-compile-time-constants
Monis Iqbal
I can't find any specific articles or specs, sorry.
jjnguy
A: 

The code you have is equivilant because string literals are automatically interned by the compiler.

If you are really concerned about String performance and will be reusing the same strings over and over you should take a look at the intern method on the string class.

http://java.sun.com/javase/6/docs/api/java/lang/String.html#intern()

anio
No, no, *no!* Interning strings at will for “performance reasons” (the term already almost makes me puke) is *wrong*. Unless you’re doing high-volume string processing it won’t give you anything but trouble.
Bombe
You have any thing other than disgust to back up your baseless claims? I gave a good reason to use intern, a case in which the same set of strings will need to be reused over and over. Why create new ones everytime? The only downside to intern is that the strings which are interned can never be garbage collected. I assume that is what you are complaining about. But if you will be reusing the same strings throughout the life of the program then it does make sense to intern them vs. creating new ones everytime.
anio
See this it gives pros and cons of intern. http://mindprod.com/jgloss/interned.html
anio
The answer to the question "Why not call `intern()`" is given in exactly the "Java glossary" article you provided -- *All `String` literals present at compile time are automatically interned.*Think it through. You have a string that's not present at compile time, but varies based on some run-time information (user input, console arguments, etc).If you only create the string once, and pass it around, `intern()` doesn't gain you anything.If you create the *same* run-time string *repeatedly*, then you're probably violating DRY and the best optimization is probably to get rid of the repeats.
David Moles
+8  A: 

This is covered in the Java Language Spec:

Each string literal is a reference (§4.3) to an instance (§4.3.1, §12.5) of class String (§4.3.3). String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions (§15.28)-are "interned" so as to share unique instances, using the method String.intern.

You can also see for yourself using the javap tool.

For this code:

System.out.println("Efficiently stored String");
final String memFriendly = "Efficiently stored String";
System.out.println(memFriendly);

javap gives the following:

0:   getstatic     #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3:   ldc       #3; //String Efficiently stored String
5:   invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8:   getstatic     #2; //Field java/lang/System.out:Ljava/io/PrintStream;
11:  ldc       #3; //String Efficiently stored String
13:  invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
McDowell
thanks for digging this.My use case is that I have Strings in my code (which will be called more than once) that are used only once, think of logger.info("Log this");Now will making this string a static final improve performance?
Monis Iqbal
Using a reference to a static final field is unlikely to have any performance difference over an inlined literal. Since Hotspot performs so much optimisation at runtime, the only way to tell if there is a measurable difference would be to measure it. A related question on microbenchmarks: http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java
McDowell
thanks. I also used javap and compared the output of static final against inline version. Both were exactly same.You are right about runtime optimizations by Hotspot and that is what confused my at the first instance, how can I guarantee that one methodology is better such that I can use it as a best practice.
Monis Iqbal
@Monis: If you are calling `logger.info("Log this");` a lot in your application, the time spent making the method call, in the method call, and especially logging the output to disk will far, far, far outweigh any differences in speed between the way Strings are stored.
Grant Wagner
@Grant k, and what if the String is quite long?
Monis Iqbal
+1  A: 
public static void main(String[] args) {
 System.out.println("Hello world!");

 String hola = "Hola, mundo!";
 System.out.println(hola);
}

Here is what javap shows as the disassembly for this code:

0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3:   ldc     #22; //String Hello world!
5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8:   ldc     #30; //String Hola, mundo!
10:  astore_1
11:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
14:  aload_1
15:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
18:  return

Looks like the second string is being stored, whereas the first one is simply passed to the method directly.

This was built with Eclipse's compiler, which may explain differences in my answer and McDowell's.

Update: Here are the results if hola is declared as final (results in no aload_1, if I'm reading this right then it means this String is both stored and inlined, as you might expect):

0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3:   ldc     #22; //String Hello world!
5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8:   ldc     #30; //String Hola, mundo!
10:  astore_1
11:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
14:  ldc     #30; //String Hola, mundo!
16:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
19:  return
matt b
Have you tried using `final` for `hola`?
notnoop
Well, that's normal as the two strings have different text while in McDowell they are the same.
gizmo
whoa! thanks for digging this.My use case is that I have Strings in my code (which will be called more than once) that are used only once, think of logger.info("Log this");Now will making this string a static final improve performance?
Monis Iqbal
@msaeed, updated my answer with results for using `final`
matt b