Toute réponse à votre question dépendra de l'implémentation de la JVM et de la version de Java actuellement utilisée. Je pense que c'est une question déraisonnable à poser lors d'un entretien.
Java 8
Sur ma machine, avec Java 1.8.0_201, votre extrait donne le résultat suivant en bytecode
L0
LINENUMBER 13 L0
LDC "First"
ASTORE 1
L1
LINENUMBER 14 L1
LDC "Second"
ASTORE 2
L2
LINENUMBER 15 L2
LDC "Third"
ASTORE 3
L3
LINENUMBER 16 L3
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 3
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 4
ce qui prouve que 5 objets sont en cours de création (3 String
littéraux*, 1 StringBuilder
1 produit dynamiquement String
instance par [StringBuilder#toString
](https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/lang/CharSequence.html#toString()) ).
Java 12
Sur ma machine, avec Java 12.0.2, le bytecode est le suivant
// identical to the bytecode above
L3
LINENUMBER 16 L3
ALOAD 1
ALOAD 2
ALOAD 3
INVOKEDYNAMIC makeConcatWithConstants(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; [
// handle kind 0x6 : INVOKESTATIC
java/lang/invoke/StringConcatFactory.makeConcatWithConstants(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
// arguments:
"\u0001\u0001\u0001"
]
ASTORE 4
dont par magie change "la bonne réponse" en 4 objets puisqu'il n'y a pas d'intermédiaire StringBuilder
impliqué.
*Devons creuser un peu plus profond.
Une nouvelle instance de classe peut être créée implicitement dans les situations suivantes :
- Chargement d'une classe ou d'une interface qui contient un littéral de chaîne de caractères ( §3.10.5 ) peut créer un nouvel objet String pour représenter le littéral. (Cela ne se produira pas si une chaîne dénotant la même séquence de points de code Unicode a été internée précédemment).
En d'autres termes, lorsque vous démarrez une application, il y a déjà des objets dans le pool de cordes. Vous savez à peine ce qu'ils sont et d'où ils viennent (à moins que vous n'analysiez toutes les classes chargées pour trouver tous les littéraux qu'elles contiennent).
El java.lang.String
sera indubitablement chargée comme une classe essentielle de la JVM, ce qui signifie que tous ses littéraux seront créés et placés dans le pool.
Prenons un extrait choisi au hasard dans le code source de String
nous choisissons quelques littéraux, nous plaçons un point d'arrêt au tout début de notre programme et nous examinons si le pool contient ces littéraux.
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence,
Constable, ConstantDesc {
...
public String repeat(int count) {
// ...
if (Integer.MAX_VALUE / count < len) {
throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
" times will produce a String exceeding maximum size.");
}
}
...
}
Ils sont là en effet.
Fait intéressant, le filtrage de cet IDEA a un effet secondaire : les sous-chaînes que je recherchais ont également été ajoutées au pool. La taille du pool a augmenté de un ( "bytes String"
a été ajouté) après avoir appliqué this.contains("bytes String")
.
Où cela nous mène-t-il ?
Nous n'avons aucune idée si "First"
a été créé et interné avant que nous appelions String str1 = "First";
Nous ne pouvons donc pas affirmer avec certitude que la ligne crée une nouvelle instance.