11

For instance

 String s = "Hello" + " World";

I know there are two strings in the pool "Hello" and "World" but, does: "Hello World" go into the string pool?

If so, what about?

String s2 = new String("Hola") + new String(" Mundo");

How many strings are there in the pool in each case?

IAdapter
  • 62,595
  • 73
  • 179
  • 242
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • "String pool", or do you mean the constant pool. – President James K. Polk Jun 12 '10 at 16:22
  • I would imagine he means the String pool as the constant pool is set at compile time. – danben Jun 12 '10 at 16:27
  • 1
    mmmhh I said "string pool" because that's how it is referenced by String.intern() doc *..A pool of strings, initially empty...* ( http://java.sun.com/javase/6/docs/api/java/lang/String.html#intern%28%29 ) But, I'm not sure if that should be called "constant pool". Should it? – OscarRyz Jun 12 '10 at 16:29
  • The thing that String.intern() manipulates is the String pool, so you were correct. – President James K. Polk Jun 12 '10 at 16:33
  • Somebody told me that if used: `new String("Hola")` the `"Hola"` literal doesn't go to the string pool because there is no reference to it. – OscarRyz Jun 12 '10 at 17:16
  • Then what exactly is passed to the `String` constructor? – danben Jun 13 '10 at 20:03
  • @danben: An string that doesn't go to the string pool ( or that after going to the pool is eligible for garbage collection ) – OscarRyz Jun 14 '10 at 16:00
  • No, there's a few things wrong with that. One is that Strings are reference types, so they can't sit around on the stack. Another is that String literals are automatically interned . A third is that interned Strings can't be garbage-collected because they are always referenced by the String pool. – danben Jun 14 '10 at 16:54

6 Answers6

11

Yes, if a String is formed by concatenating two String literals it will also be interned.

From the JLS:

Thus, the test program consisting of the compilation unit (§7.3):

package testPackage;
class Test {
    public static void main(String[] args) {
        String hello = "Hello", lo = "lo";
        System.out.print((hello == "Hello") + " ");
        System.out.print((Other.hello == hello) + " ");
        System.out.print((other.Other.hello == hello) + " ");
        System.out.print((hello == ("Hel"+"lo")) + " ");
        System.out.print((hello == ("Hel"+lo)) + " ");
        System.out.println(hello == ("Hel"+lo).intern());
    }
}
class Other { static String hello = "Hello"; }
and the compilation unit:
package other;
public class Other { static String hello = "Hello"; }

produces the output:

true
true
true
true
false
true

The important lines are 4 and 5. 4 represents what you are asking in the first case; 5 shows you what happens if one is not a literal (or more generally, a compile-time constant).

danben
  • 80,905
  • 18
  • 123
  • 145
  • ...aaand how many strings are there in the pool in each case? :) – OscarRyz Jun 12 '10 at 16:16
  • 3 in the first case since 3 things have been interned ("Hello", "world", and "Hello world"). In the second case you have only two literals, so 2. – danben Jun 12 '10 at 16:20
  • 4
    in the first case there is only one String literal as the compiler has optmised the first two away. If you look at the compiles class file there is only one String literal. – Peter Lawrey Jun 12 '10 at 16:43
4

I believe in the first case the compiler will be clever and put the concatenated string in the pool (i.e. you'll have only 1 string there)

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
  • Is it true that in the second case, since there are no reference for the literals, the object in the pool is elegible for garbage collection and thus in the second case there won't be any object in the string pool? – OscarRyz Jun 12 '10 at 17:43
  • @Support - no. In the second case, the no string pool entry is created ... but not for the reasons you gave. Elibibility for garbage collection has nothing to do with implicit interning. (Indeed, for modern JVMs string in the String pool *may be* garbage collected, if they are not reachable via some other route.) – Stephen C Jun 13 '10 at 00:23
1

By way of confirming @Brian Agnew's answer, I looked at this code:

public class InternTest {
    public static void main(String[] args) {
        String s = "Hello" + ", world";
        System.out.println(s);
    }
}

This behavior is required for string literals and constant expressions which evaluate to a String.

javap -c InternTest
Compiled from "InternTest.java"
public class InternTest extends java.lang.Object{
public InternTest();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   ldc #2; //String Hello, world
   2:   astore_1
   3:   getstatic   #3; //Field java/lang/System.out:Ljava/io/PrintStream;
   6:   aload_1
   7:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   10:  return
Holger
  • 285,553
  • 42
  • 434
  • 765
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
0

If I am wrong please correct me. As per my understanding only one object is going to be created in SCP. As String s = "Hello" + " World"; is a compile time constant.So compiler will append these two strings at compile time only.And only one object will be created in SCP. If you open and see .class file you will find "HelloWorld in .class file

Pani
  • 186
  • 1
  • 3
  • 12
-1
String hello = "Hello", lo = "lo";     
//  known at compile time so created in String constant pool

System.out.print((hello == "Hello") + " ");  
// known at compile time so "Hello" is same object as in hello

System.out.print((Other.hello == hello) + " ");  
// Other.hello and hello created at compile time so referenced to same object

System.out.print((other.Other.hello == hello) + " ");  
// other.Other.hello and hello created at compile time 
// so referenced to same object

System.out.print((hello == ("Hel"+"lo")) + " ");   
//  hello and  "Hel"+"lo" both were created at compile
//  time so referenced to same object

System.out.print((hello == ("Hel"+lo)) + " ");   
// value in lo was not known in runtime so didn't 
// referenced to object in hello, instead created new object in String Pool Constant

System.out.println(hello == ("Hel"+lo).intern());  
// ("Hel"+lo).intern()  using intern function told at runtime 
// to check weather same string present in String Constant Pool, 
// and if present then reference to the same string which was already present in String Constant Pool.
milez
  • 2,201
  • 12
  • 31
-2

No. Only string literals are required to go into the pool. Compilers may optimize away the concatenation and may store additional string literals in the pool.

John
  • 259
  • 1
  • 2