Duplicata possible:
différence entre l'objet chaîne et le littéral chaîne
Disons que j'ai deux déclarations.
String one = "abc";
String two = new String("abc");
Laquelle est une mémoire de pile et laquelle est stockée en tas?
Quelle est la différence entre les deux?
Combien d'objets sont créés et comment est la référence en mémoire?
Quelle est la meilleure pratique?
Tous les objets sont stockés sur le tas (y compris leurs attributs).1
Les variables locales (y compris les arguments) contiennent toujours des valeurs ou des références primitives et sont stockées sur la pile.1
Donc, pour vos deux lignes:
String one = "abc";
String two = new String("abc");
Vous aurez deux objets sur le tas (deux objets String contenant "abc"
) et deux références, une pour chaque objet, sur la pile (à condition que one
et two
soient des variables locales).
(En fait, pour être précis, en ce qui concerne les chaînes internes telles que les littéraux de chaîne, elles sont stockées dans le soi-disant pool de chaînes.)
Combien d'objets sont créés et comment est la référence en mémoire?
Il est intéressant que vous posiez la question, car les chaînes sont spéciales dans le langage Java.
Une chose est cependant garanti: chaque fois que vous utilisez new
, vous obtiendrez en effet une référence nouvelle. Cela signifie que two
pas fera référence au même objet que one
ce qui signifie que vous aurez deux objets sur le tas après ces deux lignes de code.
1) Formellement parlant, la spécification de langage Java Java ne spécifie pas comment ni où les valeurs sont stockées en mémoire. Ceci (ou des variantes de celui-ci) est cependant la manière dont cela se fait généralement dans la pratique.
Le premier est appelé String Literal et créé au moment de compilation du programme et le second est string object et est créé au moment de l'exécution.
Comme vous l'avez utilisé nouvea mot clé dans le deuxième cas, il est donc alloué en tas.
Dans le premier cas, les objets sont créés avec le mécanisme appelé interning. Lorsque vous essayez de créer un autre littéral de chaîne représentant la même séquence de caractères, au lieu de créer un nouveau compilateur d'objets, il se référera à la chaîne précédente créée et stockée dans le pool de chaînes
Seules les instances de types primitifs (int, long, ...) sont enregistrées sur la pile. Toutes les instances de types de référence (String
, Integer
, Long
, YourTypeHere
, ...) sont enregistrées dans le tas.
UPDATE Comme indiqué dans les commentaires, les références aux instances de types de référence (c'est-à-dire les types non primitifs - Object
et ses descendants) ) peut être enregistré sur la pile. Ce sont vos variables locales.
Ce n'est pas "une meilleure pratique", c'est la façon dont fonctionne la JVM et vous ne pouvez pas la changer.
Dans votre cas, 2 objets String sont créés. En général, tous les objets sont créés sur le tas. Cependant, puisque la chaîne un est un littéral de chaîne, elle sera stockée dans le pool de chaînes (dans PermGen). Vous pouvez également utiliser la méthode intern () pour ajouter une chaîne au pool de chaînes et obtenir une référence à celui-ci.
Si les déclarations que vous avez publiées sont dans une méthode, les références seront stockées sur la pile, mais pas les objets eux-mêmes.
Quant aux meilleures pratiques, je pense que ce serait: String one = "abc"
Ceci pour 2 raisons:
EDIT: Vous pourriez être intéressé par la vérification de ce lien: Escape Analysis in Java SE 7 . Il présente quelques optimisations liées à HotSpot qui affectent l'allocation des objets.