Quelle est la différence entre ces deux déclarations suivantes?
Ssortingng s = "text"; Ssortingng s = new Ssortingng("text");
new Ssortingng("text");
crée explicitement une instance nouvelle et référentielle distincte d’un object Ssortingng
; Ssortingng s = "text";
peut réutiliser une instance du pool de constantes de la chaîne si elle est disponible.
Vous souhaiterez rarement utiliser le new Ssortingng(anotherSsortingng)
. De l’API:
Ssortingng(Ssortingng original)
: initialise un objectSsortingng
nouvellement créé afin qu’il représente la même séquence de caractères que l’argument; En d’autres termes, la chaîne nouvellement créée est une copie de la chaîne d’arguments. A moins qu’une copie explicite de l’original ne soit nécessaire, l’utilisation de ce constructeur est inutile car les chaînes sont immuables.
Examinez l’extrait suivant:
Ssortingng s1 = "foobar"; Ssortingng s2 = "foobar"; System.out.println(s1 == s2); // true s2 = new Ssortingng("foobar"); System.out.println(s1 == s2); // false System.out.println(s1.equals(s2)); // true
==
sur deux types de référence est une comparaison d’identité de référence. Deux objects equals
ne sont pas nécessairement ==
. Il est généralement faux d’utiliser ==
sur les types de référence; la plupart du temps, les equals
doivent être utilisés à la place.
Néanmoins, si pour quelque raison que ce soit, vous devez créer deux equals
mais pas une chaîne ==
, vous pouvez utiliser le new Ssortingng(anotherSsortingng)
. Il faut cependant répéter que cela est très particulier, et rarement l’intention.
class Object
– class Object
boolean Object(equals)
Les littéraux de chaîne iront dans le pool de constantes de chaîne .
Le cliché ci-dessous peut vous aider à le comprendre visuellement pour vous en souvenir plus longtemps.
Création d’objects ligne par ligne:
Ssortingng str1 = new Ssortingng("java5");
En utilisant le littéral de chaîne “java5” dans le constructeur, une nouvelle valeur de chaîne est stockée dans le pool de constantes de chaîne. En utilisant un nouvel opérateur, un nouvel object chaîne est créé dans le tas avec la valeur “java5”.
Ssortingng str2 = "java5"
La référence “str2” est pointée vers la valeur déjà stockée dans le pool de chaînes constantes
Ssortingng str3 = new Ssortingng(str2);
Un nouvel object chaîne est créé dans le tas avec la même valeur que la référence par “str2”
Ssortingng str4 = "java5";
La référence “str4” pointe vers la valeur déjà stockée dans le pool de chaînes constantes
Total des objects: Heap – 2, Pool – 1
Lectures complémentaires sur la communauté Oracle
On crée une chaîne dans le pool Ssortingng Constant
Ssortingng s = "text";
l’autre crée une chaîne dans le pool constant ( "text"
) et une autre chaîne dans un espace de stack normal. Les deux chaînes auront la même valeur, celle de “text”.
Ssortingng s = new Ssortingng("text");
s
est alors perdu (éligible au GC) si inutilisé ultérieurement.
Les littéraux de chaîne sont réutilisés. Si vous utilisez "text"
à plusieurs endroits de votre classe, il s’agira en fait d’une seule et unique chaîne (c’est-à-dire de plusieurs références à la même chaîne dans le pool).
Le concept est appelé “interning” par le JLS.
Passage pertinent de JLS 7 3.10.5 :
De plus, un littéral de chaîne fait toujours référence à la même instance de la classe Ssortingng. C’est parce que les littéraux de chaîne – ou, plus généralement, les chaînes qui sont les valeurs des expressions constantes (§15.28) – sont “internés” de manière à partager des instances uniques, en utilisant la méthode Ssortingng.intern.
Exemple 3.10.5-1. Littéraux de chaîne
Le programme composé de l’unité de compilation (§7.3):
package testPackage; class Test { public static void main(Ssortingng[] args) { Ssortingng hello = "Hello", lo = "lo"; System.out.print((hello == "Hello") + " "); System.out.print((Other.hello == hello) + " "); System.out.print((other.Other.hello == hello) + " "); System.out.print((hello == ("Hel"+"lo")) + " "); System.out.print((hello == ("Hel"+lo)) + " "); System.out.println(hello == ("Hel"+lo).intern()); } } class Other { static Ssortingng hello = "Hello"; }
et l’unité de compilation:
package other; public class Other { public static Ssortingng hello = "Hello"; }
produit la sortie:
true true true true false true
JVMS 7 5.1 dit :
Un littéral de chaîne est une référence à une instance de classe Ssortingng et est dérivé d’une structure CONSTANT_Ssortingng_info (§4.4.3) dans la représentation binary d’une classe ou d’une interface. La structure CONSTANT_Ssortingng_info donne la séquence de points de code Unicode constituant le littéral de chaîne.
Le langage de programmation Java requirejs que les littéraux de chaîne identiques (c’est-à-dire les littéraux contenant la même séquence de points de code) doivent faire référence à la même instance de classe Ssortingng (JLS §3.10.5). De plus, si la méthode Ssortingng.intern est appelée sur une chaîne quelconque, le résultat est une référence à la même instance de classe qui serait renvoyée si cette chaîne apparaissait comme un littéral. Ainsi, l’expression suivante doit avoir la valeur true:
("a" + "b" + "c").intern() == "abc"
Pour dériver un littéral de chaîne, la machine virtuelle Java examine la séquence de points de code donnée par la structure CONSTANT_Ssortingng_info.
Si la méthode Ssortingng.intern a déjà été appelée sur une instance de classe Ssortingng contenant une séquence de points de code Unicode identique à celle donnée par la structure CONSTANT_Ssortingng_info, le résultat de la dérivation de littéral de chaîne est une référence à cette même instance de classe Ssortingng.
Sinon, une nouvelle instance de classe Ssortingng est créée contenant la séquence de points de code Unicode donnée par la structure CONSTANT_Ssortingng_info; une référence à cette instance de classe est le résultat d’une dérivation littérale de chaîne. Enfin, la méthode intern de la nouvelle instance Ssortingng est appelée.
Il est également instructif d’examiner l’implémentation du bytecode sur OpenJDK 7.
Si on décomstack:
public class SsortingngPool { public static void main(Ssortingng[] args) { Ssortingng a = "abc"; Ssortingng b = "abc"; Ssortingng c = new Ssortingng("abc"); System.out.println(a); System.out.println(b); System.out.println(a == c); } }
nous avons sur la réserve constante:
#2 = Ssortingng #32 // abc [...] #32 = Utf8 abc
et main
:
0: ldc #2 // Ssortingng abc 2: astore_1 3: ldc #2 // Ssortingng abc 5: astore_2 6: new #3 // class java/lang/Ssortingng 9: dup 10: ldc #2 // Ssortingng abc 12: invokespecial #4 // Method java/lang/Ssortingng."":(Ljava/lang/Ssortingng;)V 15: astore_3 16: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 19: aload_1 20: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/Ssortingng;)V 23: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 26: aload_2 27: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/Ssortingng;)V 30: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 33: aload_1 34: aload_3 35: if_acmpne 42 38: iconst_1 39: goto 43 42: iconst_0 43: invokevirtual #7 // Method java/io/PrintStream.println:(Z)V
Notez comment:
0
et 3
: la même constante ldc #2
est chargée (les littéraux) 12
: une nouvelle instance de chaîne est créée (avec l’argument #2
) 35
: a
et c
sont comparés comme objects réguliers avec if_acmpne
La représentation de chaînes constantes est assez magique sur le bytecode:
new Ssortingng
) et la citation de JVMS ci-dessus semble dire que chaque fois que le Utf8 indiqué est le même, alors des instances identiques sont chargées par ldc
.
J’ai fait des tests similaires pour les champs et:
static final Ssortingng s = "abc"
pointe vers la table des constantes via l’ atsortingbut ConstantValue ldc
Conclusion : le pool de chaînes prend en charge le bytecode direct et la représentation de la mémoire est efficace.
Bonus: comparez cela au pool Integer , qui ne prend pas directement en charge le bytecode (c.-à-d. Aucun analogue CONSTANT_Ssortingng_info
).
Pensez à "bla"
étant une fabrique magique comme Ssortingngs.createSsortingng("bla")
(pseudo). La fabrique contient un pool de toutes les chaînes créées de cette manière.
S’il est appelé, il vérifie s’il existe déjà une chaîne dans le pool avec cette valeur. Si true, il retourne cet object ssortingng, donc les chaînes obtenues de cette manière sont bien le même object.
Sinon, il crée un nouvel object chaîne en interne, l’enregistre dans le pool et le renvoie. Ainsi, lorsque la même valeur de chaîne est interrogée la prochaine fois, elle renvoie la même instance.
La création manuelle d’une new Ssortingng("")
remplace ce comportement en ignorant le pool de littéral de chaîne. Donc, l’égalité doit toujours être vérifiée en utilisant equals()
qui compare la séquence de caractères au lieu de l’égalité de référence de l’object.
Une façon simple de comprendre la différence est la suivante: –
Ssortingng s ="abc"; Ssortingng s1= "abc"; Ssortingng s2=new Ssortingng("abc"); if(s==s1){ System.out.println("s==s1 is true"); }else{ System.out.println("s==s1 is false"); } if(s==s2){ System.out.println("s==s2 is true"); }else{ System.out.println("s==s2 is false"); }
la sortie est
s==s1 is true s==s2 is false
Ainsi, le nouveau Ssortingng () créera toujours une nouvelle instance.
@Braj: Je pense que vous avez mentionné l’inverse. S’il vous plait corrigez moi si je me trompe
Création d’objects ligne par ligne:
Ssortingng str1 = new Ssortingng (“java5”)
Pool- "java5" (1 Object) Heap - str1 => "java5" (1 Object)
Ssortingng str2 = “java5”
pool- str2 => "java5" (1 Object) heap - str1 => "java5" (1 Object)
Ssortingng str3 = new Ssortingng (str2)
pool- str2 => "java5" (1 Object) heap- str1 => "java5", str3 => "java5" (2 Objects)
Ssortingng str4 = “java5”
pool - str2 => str4 => "java5" (1 Object) heap - str1 => "java5", str3 => "java5" (2 Objects)
Bien qu’il soit identique du sharepoint vue des programmeurs, il a un grand impact sur les performances. Vous voudriez utiliser la première forme presque toujours.
Ssortingng str = new Ssortingng("hello")
Il vérifiera si le pool de constantes Ssortingng contient déjà la chaîne “hello”? S’il est présent, il n’appenda pas d’entrée dans le pool de constantes Ssortingng. S’il n’est pas présent, il appenda une entrée dans le pool de constantes Ssortingng.
Un object sera créé dans une zone de mémoire de tas et des points de référence str
à un object créé dans un emplacement de mémoire de segment de mémoire.
Si vous souhaitez que la référence str
à un object point contienne un pool constant Ssortingng, vous str.intern();
appeler explicitement str.intern();
Ssortingng str = "world";
Il vérifiera si le pool de constantes Ssortingng contient déjà la chaîne “hello”? S’il est présent, il n’appenda pas d’entrée dans le pool de constantes Ssortingng. S’il n’est pas présent, il appenda une entrée dans le pool de constantes Ssortingng.
Dans les deux cas, la référence str
désigne la chaîne "world"
présente dans le pool constant.