2

I am confused about these two things. I need a help. Please clear my doubt, whether String Constant Pool and String pool both are same concept. I faced this question on interview. I have already read lot of sites and blogs but, my doubt is not cleared.Please clear my doubts.

Thanks in Advance.

JDGuide
  • 6,239
  • 12
  • 46
  • 64

4 Answers4

5

Both are the same thing. String Constant Pool contains constant string objects. Constant can be defined as String object holds the value at compile time. For more refer JLS.

    String s="abc";
    String s1="def";
    String s2=s+"def";
    String s3="abc"+"def";
    System.out.println(s2==s3); // print false

But if you make s as final then

    final String s="abc";
    String s1="def";
    String s2=s+"def";
    String s3="abc"+"def";
    System.out.println(s2==s3); // print true

In above case s3 is a compile time constant as s is final .

amicngh
  • 7,831
  • 3
  • 35
  • 54
3

The String pool (= "String constant pool"):

The Constant Pool (not focused on Strings, but does include Strings):

Glen Best
  • 22,769
  • 3
  • 58
  • 74
2

I thought about it and I'm not sure but the string pool may refer to the string literal pool, stuff like String apple = "apple"; where as the String constant pool may refer to the constant string objects like those using the keyword final, although to receive a question with tricky semantics like that would annoy me if I got it in an interview

aaronman
  • 18,343
  • 7
  • 63
  • 78
2

String Pool (String Constant/Memory/Literals Pool) vs Constant Pool

When compiler meets any string literal, compiler puts it into String Constant Pool. All the method or class variables refer to that string constant pool;

class MemoryModel { final String s = "abc"; String s5 = "abc";}

:
String s1 = "abc";
MemoryModel mm = new MemoryModel(); 
System.out.println("abc".hashCode()); //12345
System.out.println(mm.s.hashCode()); //12345
System.out.println(mm.s5.hashCode()); //12345
System.out.println(s1.hashCode()); //12345

String "abc" will go to String pool, whereas s,s5 will go in constant pool (or Runtime Constant Pool) of class MemoryModel. ‘s1’ is method local variable so it’ll be saved in JVM frame.

enter image description here

  • A string literal always refers to the same instance of class String.
  • Literal strings in any class of any package represent references to the same String object.
  • Strings computed by constant expressions are computed at compile time and then treated as if they were literals.

Example 2

public method(){
      final String s="abc";
      String s1="def";
      final String s2=s+s1;
      String s3=s+"def";
      String s4="abc"+"def";
}

For above method nothing will be saved in Class Constant Pool. “abc”, “def”, and “abcdef” will be saved in String pool.

"abcdef".hashCode() == ("abc" + "def").hashCode() //true

Bytecode for above method;

   0: ldc           #19                 // String abc
   2: astore_1
   3: ldc           #21                 // String def
   5: astore_2
   6: new           #23                 // class java/lang/StringBuilder
   9: dup
  10: ldc           #19                 // String abc
  12: invokespecial #25                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  15: astore_3
  16: aload_3
  17: aload_2
  18: invokevirtual #28                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  21: invokevirtual #32                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  24: astore        4
  26: ldc           #36                 // String abcdef
  28: astore        5
  30: ldc           #36                 // String abcdef
  32: astore        6
  34: return

Above bytecode suggests that nothing is put into CP (Constant Pool). For above code s3 == s4 and s3 == “abcdef” because all final constants are replaced with their value at the time of compilation. So the above code will be converted to this;

  final String s="abc";
  String s1="def";
  final String s2=new StringBuilder("abc").append(s1).toString();
  String s3="abc"+"def";
  String s4="abc"+"def";

But if ‘s’ is not final then

  String s="abc";
  String s1="def";
  final String s2=new StringBuilder(s).append(s1).toString();
  String s3=new StringBuilder(s).append("def").toString();
  String s4="abc"+"def";

In above code, s2 and s3 will be pointing a new instance of String having char[]. So s3 and s4 are not same.

Example 3

public class MemoryModel {  
    final String s="abc";
    String s1="def";
    final String s2=s+s1;
    String s3=s+"def";
    String s4="abc"+"def";
    String s5=s2;
}

Bytecode for this is pretty much similar to above bytecode. But you’ll see few more entries of putfield and getfield which tells us that constant are put into CP.

Let’s compare byte code for above code;

With Final 's'

  21: ldc           #8                  // String abc
  23: invokespecial #27                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  26: aload_0
  27: getfield      #23                 // Field s1:Ljava/lang/String;
  30: invokevirtual #30                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  33: invokevirtual #34                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  36: putfield      #38                 // Field s2:Ljava/lang/String;

Without Final 's'

  21: aload_0
  22: getfield      #18                 // Field s:Ljava/lang/String;
  25: invokestatic  #26                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
  28: invokespecial #32                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  31: aload_0
  32: getfield      #22                 // Field s1:Ljava/lang/String;
  35: invokevirtual #35                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  38: invokevirtual #39                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  41: putfield      #43                 // Field s2:Ljava/lang/String;

And

With Final 's'

  39: aload_0
  40: ldc           #40                 // String abcdef
  42: putfield      #42                 // Field s3:Ljava/lang/String;

Without Final 's'

  44: aload_0
  45: new           #24                 // class java/lang/StringBuilder
  48: dup
  49: aload_0
  50: getfield      #18                 // Field s:Ljava/lang/String;
  53: invokestatic  #26                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
  56: invokespecial #32                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  59: ldc           #20                 // String def
  61: invokevirtual #35                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  64: invokevirtual #39                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  67: putfield      #45                 // Field s3:Ljava/lang/String;   

This comparison also proves that the value of final variable is replaced at the time of comparison. And the constant fields are saved into CP. So if ‘s’ is not final then the value of ‘s is taken from CP using getfield.

Amit Kumar Gupta
  • 7,193
  • 12
  • 64
  • 90