0

In case of string literal :-

String s = "happ"

s = s.concat("y")  //line1
  • 1
    You know you can verify that easily using `==` comparison right? If `a == b` while `a` and `b` have been obtained through different code paths it probably means this string has been interned. – Dici Sep 22 '18 at 21:44
  • As a general rule, if it is a literal (wrapped in quotes) it is in the string pool, if it is an object created at runtime (`new String("x")`) that variable will not be interned. – vandench Sep 22 '18 at 21:52
  • "on heap or in string constant pool" object is stored in heap, string constant pool is just *part of it* for string literals (which also are objects). Anyway result of `s.concat("y")` will not be automatically placed in string constant pool (there is no need as string pool was created to reuse literals since they have high chance to be reused). "So here, "Birth" is in constant pool," only `"Birth"` literal used as argument passed to `new String(...)` constructor. That constructor will become *separate* copy of `"Birth"` but will not be in string constant pool. – Pshemo Sep 22 '18 at 21:56
  • @user10402056 note that the constant pool is also inside the heap. It's just a reserved space that doesn't get GC'ed (to my knowledge). – Dici Sep 22 '18 at 22:04
  • @vandench so you mean in case of ... new String("x"), x will not be interned? Btw my question was about the result of concatenation, where is the result of concat stored? In case we are concatenating objects from pool vs the ones created using new keyword. –  Sep 22 '18 at 22:06
  • @user10402056 Yes, that is what I meant. – Pshemo Sep 22 '18 at 22:07
  • @Dici yes I understand that. I used the term to differentiate between the two spaces. –  Sep 22 '18 at 22:07
  • @Pashemo so basically concat method puts concatenated string on heap area (other than constant pool). Thanks a ton! –  Sep 22 '18 at 22:09
  • @user10402056 the literal "x" will be interned, the variable it is wrapped in will not. If the concatenation can occur statically at compile time, the compiler will do so. – vandench Sep 22 '18 at 22:09
  • @vandench Sorry I didn't understand what you mean when you say ..."If the concatenation can occur statically at compile time, the compiler will do so" thanks! –  Sep 22 '18 at 22:11
  • Yes, you can easily test it with `"abc"=="ab".concat("c")`. Since it is evaluated from left to right at first `"abc"` will be placed in constant pool, then `"ab".concat("c")` will be evaluated, also to `"abc"` but this string will not be interned (result string will not come from pool so its reference will be different than one from pool making result of `==` false). Demo: https://ideone.com/O2LHnX – Pshemo Sep 22 '18 at 22:13
  • 1
    "If the concatenation can occur statically at compile time" is probably referring to situations like `"ab"+"c"` (notice it is `+` not `concat` method) then compiler will change it into `"abc"` which will be interned. This should interest you [Comparing strings with == which are declared final in Java](https://stackoverflow.com/q/19418427) – Pshemo Sep 22 '18 at 22:14
  • +1 to what Pshemo said. I guess the reason is that `"ab" + "c` can easily be simplified just by having access to the program's syntax tree, whereas anything that involves an assignment requires some way of storing and managing variables, which is only available at run time. – Dici Sep 22 '18 at 22:17
  • @user10402056 https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28 – vandench Sep 22 '18 at 22:17
  • thanks @Pshemo for making me understand this, your explanation was really useful! –  Sep 23 '18 at 18:40
  • You can just look at the definition of concat() method in String class. It returns "return new String(buf, true);" a new String object, which is going to be stored in Heap definitely. – nikhil bansal Sep 24 '18 at 12:34

2 Answers2

3

In your first example:

  String s = "happ";
  s = s.concat("y");

By the time these statement have been executed1, String objects have been created in the string pool to represent (respectively) the "happ" literal, and the "y" literal.

The execution of the second statement creates a new String object that represents the string "happy". This object is NOT in the string pool.


I wanted to specifically clear this doubt on where string stores the result of concat method when operated on strings from pool vs heap.

It is created in the heap2, not the string pool. Specifically.

The ONLY method in the String API that creates objects in the string pool is String.intern(). (That includes constructors.)


1 - Note my careful choice of words here. If you are executing the statements for the first time, the creation of the objects in the string pool may have happened during the execution of the statements. Or it may have happened before. The exact timing is implementation specific. However, the JLS guarantees that it won't happen more than once for the same literal.

2 - Note that for a modern HotSpot JVM, the string pool is in the regular heap. It is not a separate space. The string pool is effectively just a (JVM private) data structure.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • I know, strictly speaking, that was illegal, but I very much enjoyed pushing you over the 500K boundary. I guess I will never get there myself, but helping others to make that ... just feels good. Always a pleasure to look at your content! – GhostCat Oct 01 '18 at 07:55
1

Let's just try it out.

String s = "happ";
s = s.concat("y");

System.out.println(s == "happy"); // false
s = s.intern();
System.out.println(s == "happy"); // true

String s1 = new String("Birth");
s1 = s1.concat("day");

System.out.println(s1 == "Birthday"); // false
s1 = s1.intern();
System.out.println(s1 == "Birthday"); // true

So yeah, it just doesn't matter. Only literals are being interned here, not dynamically constructed values (unless explicitly interned).

Dici
  • 25,226
  • 7
  • 41
  • 82
  • `s.equals("happy")` is true because it is value equality but `==` is reference equality. For example, `"a" == new String("a")` is always false while `"a".equals(new String("a"))` is always true. Check this answer for more details: https://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java/513839#513839 – Dici Sep 22 '18 at 22:40
  • one side-note, besides these proofs about interning a String, there are zero profit calling `intern` explicitly in an application... – Eugene Sep 27 '18 at 09:34