web-dev-qa-db-fra.com

Différence entre objet chaîne et littéral chaîne

Quelle est la différence entre

String str = new String("abc");

et

String str = "abc";
235
user395617

Lorsque vous utilisez un littéral de chaîne, la chaîne peut être internée , mais lorsque vous utilisez new String("..."), vous obtenez un nouveau objet string.

Dans cet exemple, les deux littéraux de chaîne font référence au même objet:

String a = "abc"; 
String b = "abc";
System.out.println(a == b);  // true

Ici, 2 objets différents sont créés et ils ont des références différentes:

String c = new String("abc");
String d = new String("abc");
System.out.println(c == d);  // false

En général, vous devriez utiliser la notation littérale de chaîne lorsque cela est possible. Il est plus facile à lire et donne au compilateur une chance d’optimiser votre code.

202
Mark Byers

Un littéral chaîne est un concept de langage Java. C'est un littéral de chaîne:

"a String literal"

Un objet String est une instance individuelle de la classe Java.lang.String.

String s1 = "abcde";
String s2 = new String("abcde");
String s3 = "abcde";

Tous sont valables, mais ont une légère différence. s1 fera référence à un objet interné String. Cela signifie que la séquence de caractères "abcde" sera stockée à un emplacement central et que, chaque fois que le même littéral "abcde" sera utilisé à nouveau, la machine virtuelle Java ne créera pas de nouvel objet String mais utilisera la référence du - mis en cache Chaîne.

s2 est censé être un nouvel objet String, nous avons donc dans ce cas:

s1 == s2 // is false
s1 == s3 // is true
s1.equals(s2) // is true
86
Andreas_D

La réponse longue est disponible ici , je vais donc vous donner la réponse courte.

Quand tu fais ça:

String str = "abc";

Vous appelez la méthode intern() sur String . Cette méthode fait référence à un pool interne d'objets String. Si la chaîne sur laquelle vous avez appelé intern() réside déjà dans le pool, une référence à celle-ci String est affectée à str. Si ce n'est pas le cas, le nouveau String est placé dans le pool et une référence à ce dernier est ensuite attribuée à str.

Étant donné le code suivant:

String str = "abc";
String str2 = "abc";
boolean identity = str == str2;

Lorsque vous vérifiez l'identité de l'objet en effectuant == (vous demandez littéralement: ces deux références pointent-elles vers le même objet?), Vous obtenez true.

Cependant, vous n'avez pas pour intern()Strings. Vous pouvez forcer la création sur un nouveau Object sur le tas en procédant comme suit:

String str = new String("abc");
String str2 = new String("abc");
boolean identity = str == str2;

Dans ce cas, str et str2 sont des références à différents Objects, dont aucun n'a été interné , de sorte que lorsque vous testez l'identité Object à l'aide de ==, vous obtiendrez false.

En termes de bonne pratique de codage: ne pas utilisez == pour vérifier l’égalité des chaînes, utilisez plutôt .equals().

40
Jon

Comme les cordes sont immuables, quand vous le faites:

String a = "xyz"

lors de la création de la chaîne, la machine virtuelle Java recherche dans le groupe de chaînes s'il existe déjà une valeur de chaîne "xyz", si 'a' sera simplement une référence de cette chaîne et qu'aucun nouvel objet String n'est créé.

Mais si vous dites:

String a = new String("xyz")

vous forcez la JVM à créer une nouvelle référence String, même si "xyz" se trouve dans son pool.

Pour plus d'informations, lisez this .

36
Awin

"abc" est une chaîne littérale.

En Java, ces chaînes littérales sont regroupées en interne et la même instance String de "abc" est utilisée partout où ce littéral de chaîne est déclaré dans votre code. Donc, "abc" == "abc" sera toujours vrai, car ils sont tous deux la même instance de String.

En utilisant la méthode String.intern() , vous pouvez ajouter n'importe quelle chaîne de votre choix aux chaînes regroupées en interne. Elles seront conservées en mémoire jusqu'à la sortie de Java.

D'autre part, l'utilisation de new String("abc") créera un nouvel objet chaîne en mémoire, qui est logiquement identique au littéral "abc". "abc" == new String("abc") sera toujours faux, car même s'ils sont logiquement égaux, ils font référence à des instances différentes.

Enrouler un constructeur String autour d'un littéral chaîne n'a aucune valeur, il utilise simplement inutilement plus de mémoire que nécessaire.

17
krock

String est une classe dans Java différente des autres langages de programmation. Donc, comme pour chaque classe, la déclaration et l'initialisation de l'objet sont

String st1 = new String();

ou

String st2 = new String("Hello"); 
String st3 = new String("Hello");

Ici, st1, st2 et st3 sont des objets différents.

C'est:

st1 == st2 // false
st1 == st3 // false
st2 == st3 // false

Parce que st1, st2, st3 font référence à 3 objets différents et == vérifie l'égalité dans l'emplacement mémoire, d'où le résultat.

Mais:

st1.equals(st2) // false
st2.equals(st3) // true

Ici, la méthode .equals() vérifie le contenu et le contenu de st1 = "", st2 = "hello" et st3 = "hello". D'où le résultat.

Et dans le cas de la déclaration de chaîne

String st = "hello";

Ici, intern() la méthode de String class est appelée et vérifie si "hello" est dans le pool interne et si ce n'est pas le cas, elle est ajoutée au pool interne et si "hello" existe dans intern pool, alors st pointera vers la mémoire du "hello" existant.

Donc en cas de:

String st3 = "hello";
String st4 = "hello"; 

Ici:

st3 == st4 // true

Parce que st3 et st4 pointant vers la même adresse mémoire.

Aussi:

st3.equals(st4);  // true as usual
7
NCA

Dans le premier cas, deux objets sont créés.

Dans le second cas, c'est juste un.

Bien que les deux manières str se réfère à "abc".

6
sushil bharwani

Certains démontages sont toujours intéressants ...

$ cat Test.Java 
public class Test {
    public static void main(String... args) {
        String abc = "abc";
        String def = new String("def");
    }
}

$ javap -c -v Test
Compiled from "Test.Java"
public class Test extends Java.lang.Object
  SourceFile: "Test.Java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method  #7.#16;  //  Java/lang/Object."<init>":()V
const #2 = String  #17;     //  abc
const #3 = class   #18;     //  Java/lang/String
const #4 = String  #19;     //  def
const #5 = Method  #3.#20;  //  Java/lang/String."<init>":(Ljava/lang/String;)V
const #6 = class   #21;     //  Test
const #7 = class   #22;     //  Java/lang/Object
const #8 = Asciz   <init>;
...

{
public Test(); ...    

public static void main(Java.lang.String[]);
  Code:
   Stack=3, Locals=3, Args_size=1
    0:    ldc #2;           // Load string constant "abc"
    2:    astore_1          // Store top of stack onto local variable 1
    3:    new #3;           // class Java/lang/String
    6:    dup               // duplicate top of stack
    7:    ldc #4;           // Load string constant "def"
    9:    invokespecial #5; // Invoke constructor
   12:    astore_2          // Store top of stack onto local variable 2
   13:    return
}
5
aioobe

En plus des réponses déjà postées, voir aussi this excellent article sur javaranch.

5
Zaki

Selon documentation de classe String ils sont équivalents.

La documentation de String(String original) indique également que: Sauf si une copie explicite de l'original est nécessaire, l'utilisation de ce constructeur est inutile car les chaînes sont immuables.

Recherchez d'autres réponses, car il semble que la documentation de Java soit trompeuse :(

3
Michał Niklas

Voici quelques comparaisons:

String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");

System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2)); //true

System.out.println(s1 == s3);   //false
System.out.println(s1.equals(s3)); //true

s3 = s3.intern();
System.out.println(s1 == s3); //true
System.out.println(s1.equals(s3)); //true

Lorsque intern() est appelée, la référence est modifiée.

2
JavaFreak

Il existe une différence subtile entre l'objet String et le littéral de chaîne.

String s = "abc"; // creates one String object and one reference variable

Dans ce cas simple, "abc" ira dans le pool et s s'y référera.

String s = new String("abc"); // creates two objects,and one reference variable

Dans ce cas, étant donné que nous avons utilisé le mot clé new, Java créera un nouvel objet String dans la mémoire normale (sans pool) et s s'y référera. . De plus, le littéral "abc" sera placé dans le pool.

1
Kamal

String s = new String("FFFF") crée 2 objets: "FFFF" string et String object, qui pointe sur "FFFF" string, c'est donc comme pointeur à pointeur (référence à référence, je ne suis pas passionné avec terminologie).

On dit que vous ne devriez jamais utiliser new String("FFFF")

0
foret