Comment une chaîne peut-elle être initialisée avec «»?

154

Si String est une classe comme une autre, comment peut-elle être initialisée à l'aide de guillemets doubles?

jeux séparés
la source
25
String est une classe VIP. " "est déjà une chaîne!
johnchen902
2
Aucune signification particulière. Je voulais simplement dire très important. Autrement dit, java.lang.Stringayez un traitement spécial du langage Java.
johnchen902
16
Qui a dit que cette chaîne est "une classe comme les autres"? C'est une classe très spéciale, pas comme les autres. Puisque votre supposition est fausse, la question ne peut pas vraiment répondre.
Eric Lippert
5
Ce n'est pas parce que la supposition est fausse que cela ne signifie pas que la question ne peut pas répondre. Et la bonne réponse a déjà 197 voix.
Koray Tugay

Réponses:

293

La chaîne Java est spéciale

Les concepteurs de Java ont décidé de conserver les types primitifs dans un langage orienté objet, au lieu de faire de tout un objet, afin d'améliorer les performances du langage. Les primitives sont stockées dans la pile d'appels, qui nécessitent moins d'espaces de stockage et sont moins coûteuses à manipuler. D'autre part, les objets sont stockés dans le tas de programme, ce qui nécessite une gestion de la mémoire complexe et plus d'espaces de stockage.

Pour des raisons de performances, la chaîne Java est conçue pour se situer entre une primitive et une classe.

Par exemple

String s1 = "Hello";              // String literal
String s2 = "Hello";              // String literal
String s3 = s1;                   // same reference
String s4 = new String("Hello");  // String object
String s5 = new String("Hello");  // String object

entrez la description de l'image ici

Remarque: les littéraux de chaîne sont stockés dans un pool commun. Cela facilite le partage du stockage pour les chaînes avec le même contenu pour économiser le stockage. Stringles objets alloués via un nouvel opérateur sont stockés dans le heap, et il n'y a pas de partage de stockage pour le même contenu.

Suresh Atta
la source
72
Notez que le "pool commun" fait généralement partie du tas.
Joachim Sauer
3
@JoachimSauer Oui..avec peu d'avantages :) a ajouté cela en note.Merci de vous en souvenir.
Suresh Atta
2
Est-il donc plus rapide d'écrire String s1 = "Hello"; que String s2 = new String ("Hello") ;?
user2097804
28
J'ajouterais que dans votre exemple s1 == s2 == s3 mais s4! = S5
Alfredo Osorio
8
@AndrewJanke sur le hotspot récent jvm (7), le pool de chaînes n'est pas en perm gen et à partir de Java 8, il n'y a plus de perm gen ...
assylias
50

Java traite String comme une classe spéciale, vous pouvez l'initialiser des deux manières

  1. Attribuer directement un littéral

    String a = "adsasdf";
  2. Comme d'autres objets utilisant un nouveau mot-clé

    String a = new String("adsasdf");

Vous devez faire particulièrement attention lorsque vous souhaitez comparer avec le ==signe:

String a = "asdf";
String b = "asdf";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True

String a = new String("asdf");
String b = new String("asdf");
System.out.println(a == b);  // False
System.out.println(a.equals(b)); // True

C'est parce que dans le premier cas, les objets a et b sont conservés dans quelque chose appelé literal poolet ils font tous les deux référence au même objet, ils sont donc égaux dans les deux sens.

Mais dans le second cas, a et b font référence à différents objets, comme lorsque nous initialisons d'autres objets. ils sont donc inégaux par rapport à l' ==opérateur alors qu'ils sont égaux en valeurs.

chétan
la source
18

La chaîne reçoit un traitement spécial dans le JLS: c'est l'un des deux types non primitifs pour lesquels des littéraux existent (l'autre est Class) * .

Depuis le JLS :

Un littéral de chaîne est une référence à une instance de la classe `String [...].

* Eh bien, il y a aussi le "type nul" avec son "littéral nul" null, mais la plupart des gens ne considèrent pas le "type nul" comme un type approprié.

Joachim Sauer
la source
1
Je n'étais pas non plus au courant que le "type nul" est un type approprié en Java. Ses informations très utiles, vous devriez augmenter la taille de la police.
Grijesh Chauhan
1
@GrijeshChauhan: eh bien, le "type nul" est juste une formulation astucieuse pour permettre à n'importe lequel nulld'être affecté à n'importe quelle variable de type référence. Ce n'est pas un type intéressant, sinon.
Joachim Sauer
15

C'est une fonctionnalité du langage Java. Les chaînes littérales du code source reçoivent un traitement spécial.

La spécification du langage, ici , indique simplement qu'une chaîne littérale est de Stringtype

nos
la source
5

Le texte entre guillemets doubles crée un Stringobjet littéral .

String myString = "Some text";

Le code ci-dessus crée un Stringobjet, en utilisant des guillemets doubles.

tristan2468
la source
4

Les chaînes sont très souvent utilisées dans un langage de programmation. Puisque java est orienté objet, une chaîne est un objet. Pour éviter la nouvelle chaîne lourde ("someString"); chaque fois que vous avez besoin d'un objet string java vous permet de créer simplement un objet string en utilisant le littéral string.

Mais vous devez garder à l'esprit l'égalité des chaînes. Voici un court test JUnit pour démontrer ce que je veux dire.

    @Test
    public void stringTest() {
       // a string literal and a string object created 
       // with the same literal are equal
       assertEquals("string", new String("string"));

       // two string literals are the same string object
       assertSame("string", "string"); 

       // a string literal is not the same object instance 
       // as a string object created with the same string literal
       assertFalse("string" == new String("string"));

       // java's String.intern() method gives you the same
       // string object reference for all strings that are equal.
       assertSame("string", new String("string").intern());
    }
René Link
la source
Si vous ne pouviez initialiser une chaîne qu'avec new String(String src), vous ne pourriez même pas donner au constructeur un littéral de chaîne. Vous devrez initialiser a char [], puis utiliser le String(char [] src)consructeur pour construire la chaîne, ou vous devrez lire la chaîne à partir d'un fichier.
AJMansfield
Ce n'est pas correct. Un littéral de chaîne n'est qu'une séquence de caractères dans un fichier source entouré de guillemets doubles. Java crée automatiquement une instance d'une chaîne à l'aide de ce littéral. Par conséquent, un littéral et un objet String sont égaux, mais ils ne sont pas identiques. Java pourrait également avoir été implémenté de cette manière que vous devez utiliser la nouvelle chaîne (""); pour instancier un objet String, mais cela ne ferait que rendre notre vie plus difficile. Ainsi, lorsque vous écrivez une nouvelle chaîne ("une chaîne"), java crée un objet String pour le littéral "une chaîne" et transmet cet objet chaîne au constructeur de la nouvelle chaîne.
René Link
2

Juste pour mentionner. Un littéral de chaîne est une référence à une instance de la classe String, vous pouvez écrire du code comme ceci:

 "abc" .getBytes ();

 "a: b: c" .split (":");

 "愛" .codePointAt (0);
mkdev
la source
2

- String est une classe en Java . Vous avez raison, nous pouvons donc toujours initialiser avec le newmot - clé.

- Mais quand on fait quelque chose comme:

String s = "";

L'instruction ci-dessus est marquée par le compilateur comme étant un objet String spécial , puis JVM pendant le chargement de la classe (le chargement est effectué avant l'initialisation), voit cela ce que l'on appelle un littéral de chaîne , qui est stocké dans un pool de littéraux de chaîne .

- Ainsi, une chaîne peut être créée en utilisant new()et par la ""méthode, mais cette dernière fournit un littéral de chaîne qui reste dans le tas même s'il n'y a pas de référence à cet objet de chaîne, car il a une référence du pool de littéraux de chaîne.

Kumar Vivek Mitra
la source
2

Java effectue un processus en deux étapes pour nous.

String str = "hello";

est équivalent à

char data[] = {'h', 'e', 'l' , 'l', 'o'};
String str = new String(data);

Comme [.NET] [1] a une chose similaire.

String(Char[]) constructor

Est-ce que

String(char[] value)

Ajout de références: -

user1769790
la source
2
Le processus que vous décrivez n'est pas ce que fait réellement Java: comme d'autres l'ont déjà indiqué, "hello"est une chaîne littérale et sera placée dans le pool de constantes par le compilateur, voir JLS §3.10.5 et JVMS §5.1 .
siegi
1

Java.lang.Stringn'est pas qu'une classe. Cela fait partie intégrante du langage de base. Le compilateur a du sucre syntaxique pour cela. Par exemple, ""est comme une abréviation pour new String(""). Lorsqu'il est écrit, ""le compilateur optimise des chaînes identiques sur la même instance pour économiser de l'espace."a" + 5 == "a5" ==> true

Le compilateur a du sucre syntaxique pour beaucoup de choses, y compris ne pas avoir à boxer / déballer entre les versions d'objet et leurs types natifs, pas de parent signifie Object, constructeur par défaut, ...

Sylwester
la source
5
""n'est pas une abréviation pour new String(""). Si vous utilisez "", la première chose à faire est de rechercher des correspondances dans le pool de chaînes de la JVM et si c'est vrai, elle renverra cette chaîne. En utilisant new String(""), vous créerez toujours une nouvelle chaîne, même si la chaîne elle-même existe déjà dans le pool de chaînes (car elle ne sera pas stockée dans le pool de chaînes).
g00glen00b
J'ai mis à jour ma réponse. Les gens utilisent-ils cela à leur avantage, comme utiliser des constantes de chaîne comme un équivalent du type de symbole Lisp?
Sylwester