To answer the title question: Technically runtime only, as during compile time there is no String
pool to intern into.
However, all string literals and constant-valued strings as defined in the source files are automatically interned when the program starts up, and additional strings can be interned using the String#intern()
method.
Also, for future readers: OP's results appear to be an IDE quirk, out of all things. OP was originally entering input as a command line argument through BlueJ's custom public static void main(String string_input)
main method signature. Apparently BlueJ does some shenanigans behind the scenes to make this match the public static void main(String[] args)
signature required by the JLS, and apparently those shenanigans involve interning the input string at some point, leading to OP's results.
Edit for below answer: Looks like I made a minor reading mistake. While this answer somehow (sort of) works, it relies on the fact that string == string_input
, which I cannot confirm until OP updates the question (which apparently cannot be done as the source code has been deleted).
The answer can be found in the source code for String
:
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
Notice the last line: if beginIndex == 0
, the original String
itself is returned. Thus, in Case 1, string
is indeed pointing at the same object as string_5
, and so true
is printed.
However, if beginIndex != 0
, a new String
is created, and so string
is no longer pointing at the same object as string_5
, and so false
is printed.