I found a very old version of the API; please look whether there has been any change to String#concat() since then.
| Welcome to JShell -- Version 15
| For an introduction type: /help intro
jshell> String s1 = new String("excessive");
...> String s2 = s1.concat("detail");
...> String s3 = s2.intern();
...> String s4 = "excessivedetail";
s1 ==> "excessive"
s2 ==> "excessivedetail"
s3 ==> "excessivedetail"
s4 ==> "excessivedetail"
jshell> s1 == "excessive"
$7 ==> false
jshell> s2 == "excessivedetail"
$8 ==> true
The JLS is correct. It isn't some sort of magic formula whereby an effect takes place. It is an instruction book; all Java® implementations (or at least all those Oracle find out about) must comply strictly with the JLS and Oracle may test them for compliance.
Jesse Silverman wrote:Wait. Now I am questioning the following line from the JLS itself!
Yes. that means created with the concatenation operator +. I don't think it means a method call, not even to concat().
Strings computed by concatenation at run time are newly created and therefore distinct.
My name is Campbell Ritchie. I burnt down Greenhorn's mansion and sank his yacht.
"My name is Elmer J. Greenhorn. I own a mansion and a yacht!"
There is nothing “edge case”‑y about that. It is a standard part of the specification for Strings and intern().
. . . edge case exception that if the value of one of these concatenations has intern() called on it before the first line referencing the compile time constant , . . . .
How do you know? I couldn't find anything in the documentation for concat() to suggest that. Nor to deny that. It simply didn't say anything.
Further calls to .concat() will all produce distinct new values taking up additional heap space for each one.
Counting objects, except in very small programs, is a very error‑prone activity. It is also not totally consistent with the philosophy of OO programming. Objects should take care of themselves rather than having something else counting them.
Jesse Silverman wrote:. . . asking you to count objects . . .
I believe that what is going on is that the entire notion that the Internet collectively has echoing due to tons of outdated material being more readily accessible than current stuff, which is to say that SCP and heap entries are disjoint and distinct, is just no longer operative.
Campbell Ritchie wrote:I think that when that JLS section says, “concatenation,” I think it only means use of the + operator. I think the concat() method doesn't count, as I said yesterday.
Agree: a question on such code would be unfair, even if one of the options is “undefined”.
Jesse Silverman wrote: In this case, while the bigger problem is that people are still innocently reading user-level tutorial materials causing them to think the SCP is separate from the heap in PermGen/method area, even those who do not labor against this misconception "know" that all compile time constant string expressions are placed into the SCP first, before any of the code in the methods of their class is executing. I believe that the demo programs conclusively demonstrate that is no longer the case.
I think it's better to follow Winston Gutkowski's suggestions and have a list of situations where you should use ==:-
Jesse Silverman wrote:. . . don't use == for values equality of wrapper classes and string . . . .
If those Strings aren't interned, why aren't they eligible for GC?
Jesse Silverman wrote:. . . ten million copies of large strings to be bloating their heaps. . . . .
What a nice thing to say Thank you.
Thanks for your tireless work in representing the "We want to be creating great Java programmers . . .
Campbell Ritchie wrote:If those Strings aren't interned, why aren't they eligible for GC?
Jesse Silverman wrote:I feel like I know a lot of true statements that have remained true about the "String Literal Pool" or the "String Constant Pool", as I see it variously called in different posts and articles, even within this forum. If I understand correctly, the behavior has zero dependence on what you compile with, and solely on which JVM is running the code, what's more, I suspect that this all changed ten years ago and is only confusing people because there is so much stale information about SCP out there in old tutorials and archived discussions and old mock exam questions.
My current belief is that the following statements from the certainly great-at-the-time but possibly no longer quite true tutorial on this site may have become inoperative:
When a .java file is compiled into a .class file, any String literals are noted in a special way, just as all constants are. When a class is loaded (note that loading happens prior to initialization), the JVM goes through the code for the class and looks for String literals. When it finds one, it checks to see if an equivalent String is already referenced from the heap. If not, it creates a String instance on the heap and stores a reference to that object in the constant table. Once a reference is made to that String object, any references to that String literal throughout your program are simply replaced with the reference to the object referenced from the String Literal Pool.
A downstream conclusion from this fundamental explication that I believe is no longer applicable now is:
Strings created at run-time will always be distinct from those created from String Literals.
It is my current belief that the String Constant Pool seems to now be built up during code execution, so that if a String Literal that the JVM is considering adding or looking up in the pool has already been added to the heap and then the SCP by executing user code, it will choose that very one as the reference to add to the String Literal Pool. In the old days, as this was done before a single line of user code executed, at class loading time, that would never ever happen.
The reason this matters so much (or at all) is that the simple downstream conclusion mentioned both in that article and many other places that exam-preparers are reading is no longer operative. Instead, it instead now depends on whether the code creating the string that is only created at runtime executes before the line that references the string constant!
I never loved these questions about "how many String objects get created? Where?" which I see from some sources are indicated to be much more common in preparatory materials and mock exams than on real exams.
Referenced "Was-Great-At-The-Time-But-Confusing-To-New-Exam-Takers-Now" article from this site:
. . . because the String compression feature is like clean glass. It is transparent, and the user doesn't notice any difference. That is how a program enhancement should look
Jesse Silverman wrote:. . . off-topic for the exam, and unnecessary for those who are just trying to write . . . programs . . .
No, it is the existence of a mechanism for displaying addresses. Please confirm whether id() shows you the memory address.
Jesse Silverman wrote:. . . the difference of interpreted versus compiled-interpreted, . . .
Jesse Silverman wrote:It is mildly annoying that Python uses the keyword "is" operator to tell if two references point to the same identical instance, and == tests for content equality.
Well, by itself it is fine, but it gets annoying when you jump back and forth between Python and Java.