web-dev-qa-db-fra.com

Les chaînes sont des objets en Java, alors pourquoi n'utilisons-nous pas «nouveau» pour les créer?

Nous créons normalement des objets en utilisant le mot clé new, comme:

Object obj = new Object();

Les chaînes sont des objets, mais nous n'utilisons pas new pour les créer:

String str = "Hello World";

Pourquoi est-ce? Puis-je créer une chaîne avec new?

102
giri

En plus de ce qui a déjà été dit, String literals [c'est-à-dire des chaînes comme "abcd" Mais pas comme new String("abcd")] dans Java sont internés - cela signifie que chaque fois que vous faites référence à "abcd", vous obtenez une référence à une seule instance String, plutôt qu'à une nouvelle à chaque fois. Vous aurez donc:

String a = "abcd";
String b = "abcd";

a == b; //True

mais si tu avais

String a = new String("abcd");
String b = new String("abcd");

alors il est possible d'avoir

a == b; // False

(et si quelqu'un a besoin de le rappeler, utilisez toujours .equals() pour comparer les chaînes; == teste l'égalité physique).

Interner les littéraux de chaîne est bon car ils sont souvent utilisés plus d'une fois. Par exemple, considérez le code (artificiel):

for (int i = 0; i < 10; i++) {
  System.out.println("Next iteration");
}

Si nous n'avions pas d'internement de chaînes, "Prochaine itération" devrait être instanciée 10 fois, alors que maintenant elle ne sera instanciée qu'une seule fois.

126
danben

Les chaînes sont des objets "spéciaux" en Java. Les concepteurs de Java Java ont judicieusement décidé que les chaînes sont utilisées si souvent qu'elles ont besoin de leur propre syntaxe ainsi que d'une stratégie de mise en cache. Lorsque vous déclarez une chaîne en disant:

String myString = "something";

myString est une référence à un objet String avec une valeur de "quelque chose". Si vous déclarez plus tard:

String myOtherString = "something";

Java est suffisamment intelligent pour déterminer que myString et myOtherString sont les mêmes et les stockera dans une table de chaînes globale comme le même objet. Cela repose sur le fait que vous ne pouvez pas modifier les chaînes pour ce faire. Cela réduit la quantité de mémoire requise et peut accélérer les comparaisons.

Si, au contraire, vous écrivez

String myOtherString = new String("something");

Java créera pour vous un tout nouvel objet, distinct de l'objet myString.

31
Jamie McCrindle
String a = "abc"; // 1 Object: "abc" added to pool

String b = "abc"; // 0 Object: because it is already in the pool

String c = new String("abc"); // 1 Object

String d = new String("def"); // 1 Object + "def" is added to the Pool

String e = d.intern(); // (e==d) is "false" because e refers to the String in pool

String f = e.intern(); // (f==e) is "true" 

//Total Objects: 4 ("abc", c, d, "def").

J'espère que cela efface quelques doutes. :)

16
Crocode

C'est un raccourci. Ce n'était pas comme ça à l'origine, mais Java l'a changé.

Cette FAQ en parle brièvement. Le Java Guide de spécifications en parle aussi. Mais je ne le trouve pas en ligne.

6
Malfist

La chaîne est soumise à quelques optimisations (à défaut d'une meilleure phrase). Notez que String a également une surcharge d'opérateur (pour l'opérateur +) - contrairement aux autres objets. C'est donc vraiment un cas particulier.

6
Brian Agnew

Nous utilisons généralement des littéraux de chaîne pour éviter de créer des objets inutiles. Si nous utilisons un nouvel opérateur pour créer un objet String, il créera à chaque fois un nouvel objet.

Exemple:

String s1=“Hello“;
String s2=“Hello“;
String s3= new String(“Hello“);
String s4= new String(“Hello“);

Pour le code ci-dessus en mémoire:

enter image description here

4
Joby Wilson Mathews

En Java, les chaînes sont un cas spécial, avec de nombreuses règles qui s'appliquent uniquement aux chaînes. Les guillemets doubles obligent le compilateur à créer un objet String. Étant donné que les objets String sont immuables, cela permet au compilateur d'interner plusieurs chaînes et de créer un plus grand pool de chaînes. Deux constantes String identiques auront toujours la même référence d'objet. Si vous ne voulez pas que ce soit le cas, vous pouvez utiliser une nouvelle chaîne (""), ce qui créera un objet chaîne au moment de l'exécution. La méthode intern () était courante, pour que les chaînes créées dynamiquement soient vérifiées par rapport à la table de recherche de chaînes. Une fois une chaîne internée, la référence d'objet pointera vers l'instance de chaîne canonique.

    String a = "foo";
    String b = "foo";
    System.out.println(a == b); // true
    String c = new String(a);
    System.out.println(a == c); // false
    c = c.intern();
    System.out.println(a == c); // true

Lorsque le chargeur de classe charge une classe, toutes les constantes String sont ajoutées au pool String.

2
brianegge

Le pool littéral contient toutes les chaînes qui ont été créées sans utiliser le mot clé new.

Il y a une différence: String sans nouvelle référence est stocké dans le pool littéral String et String with new indique qu'ils sont en mémoire de tas.

Les chaînes avec new sont ailleurs dans la mémoire comme tout autre objet.

0
lavina

N'hésitez pas à créer une nouvelle chaîne avec

String s = new String("I'm a new String");

La notation habituelle s = "new String"; est plus ou moins un raccourci pratique - qui devrait être utilisé pour des raisons de performances, sauf dans les cas assez rares où vous vraiment avez besoin de chaînes qualifiées pour l'équation

(string1.equals(string2)) && !(string1 == string2)

MODIFIER

En réponse au commentaire: c'était pas destiné à être un conseil mais juste une réponse directe à la thèse des interrogateurs, que nous n'utilisons pas le 'nouveau 'mot-clé pour les chaînes, ce qui n'est tout simplement pas vrai. J'espère que cette modification (y compris ce qui précède) clarifie un peu cela. BTW - il y a quelques bonnes et bien meilleures réponses à la question ci-dessus sur SO.

0
Andreas_D

Sucre syntaxique. le

String s = new String("ABC");

la syntaxe est toujours disponible.

0
Seva Alekseyev
TString obj1 = new TString("Jan Peter");                
TString obj2 = new TString("Jan Peter");                    

if (obj1.Name == obj2.Name)                 
    System.out.println("True");
else                
    System.out.println("False");

Sortie:

Vrai

J'ai créé deux objets distincts, les deux ont un champ (ref) 'Nom'. Donc, même dans ce cas, "Jan Peter" est partagé, si je comprends bien la manière Java traite ..

0
Pete Del Fina

Vous pouvez toujours utiliser new String("string"), mais il serait plus difficile de créer de nouvelles chaînes sans littéraux de chaîne ... vous devrez utiliser des tableaux de caractères ou des octets :-) Les littéraux de chaîne ont une propriété supplémentaire: tous les mêmes littéraux de chaîne depuis n'importe quel point de classe vers la même instance de chaîne (ils sont internés).

0
Peter Štibraný

Parce que String est une classe immuable en Java.

Maintenant, pourquoi est-il immuable? Comme String est immuable, il peut donc être partagé entre plusieurs threads et nous n'avons pas besoin de synchroniser le fonctionnement de String en externe. As String est également utilisé dans le mécanisme de chargement de classe. Donc, si String était mutable, Java.io.writer aurait pu être changé en abc.xyz.mywriter

0
Mr37037

Il n'est presque pas nécessaire de créer une nouvelle chaîne car le littéral (les caractères entre guillemets) est déjà un objet String créé lors du chargement de la classe Host. Il est parfaitement légal d'invoquer des méthodes sur un littéral et don, la principale distinction est la commodité offerte par les littéraux. Ce serait une douleur et un gaspillage de dents importants si nous devions créer un tableau de caractères et le remplir caractère par caractère et en faisant une nouvelle chaîne (tableau de caractères).

0
mP.