web-dev-qa-db-fra.com

Un littéral String est-il stocké sur la pile? Une nouvelle chaîne est-elle stockée sur la pile?

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?

30
Some Java Guy

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 twopas 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.

23
aioobe

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

7
Chandra Sekhar

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.

4
Victor Sorokin

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:

  1. Le code est plus propre
  2. Les chaînes internées peuvent être comparées à == qui est plus rapide qu'égal. Mais vous devrez intern () toute chaîne non littérale avant de pouvoir la comparer.

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.

3
Filip