Différence entre object chaîne et chaîne littérale

Quelle est la différence entre

Ssortingng str = new Ssortingng("abc"); 

et

 Ssortingng str = "abc"; 

    Lorsque vous utilisez un littéral de chaîne, la chaîne peut être internée , mais lorsque vous utilisez new Ssortingng("...") vous obtenez un nouvel object chaîne.

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

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

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

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

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

    Un littéral de chaîne est un concept de langage Java. Ceci est un littéral Ssortingng:

     "a Ssortingng literal" 

    Un object Ssortingng est une instance individuelle de la classe java.lang.Ssortingng .

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

    Tous sont valables, mais ont une légère différence. s1 fera référence à un object Ssortingng interne . Cela signifie que la séquence de caractères "abcde" sera stockée à un endroit central, et chaque fois que le même littéral "abcde" sera utilisé à nouveau, la JVM ne créera pas un nouvel object Ssortingng mais utilisera la référence de la chaîne en cache .

    s2 est garanti pour être un nouvel object Ssortingng , donc dans ce cas, nous avons:

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

    La longue réponse est disponible ici , alors je vais vous en donner une brève.

    Lorsque vous faites cela:

     Ssortingng str = "abc"; 

    Vous appelez la méthode intern() sur Ssortingng . Cette méthode référence un pool interne d’objects Ssortingng . Si la chaîne que vous avez appelée intern() réside déjà dans le pool, une référence à cette Ssortingng est affectée à str . Dans le cas contraire, la nouvelle Ssortingng est placée dans le pool et une référence à celle-ci est alors atsortingbuée à str .

    Vu le code suivant:

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

    Lorsque vous vérifiez l’identité d’un object en faisant == (vous demandez littéralement: ces deux références pointent-elles vers le même object?), Vous obtenez la true .

    Cependant, vous n’avez pas besoin d’ intern() Ssortingngs . Pour ce faire, vous pouvez forcer la création sur un nouvel Object sur le tas:

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

    Dans cette instance, str et str2 sont des références à différents Objects , qui n’ont pas été internés , de sorte que lorsque vous testez une identité d’ Object utilisant == , vous obtiendrez false .

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

    Comme les chaînes sont immuables, quand vous faites:

     Ssortingng a = "xyz" 

    lors de la création de la chaîne, la JVM recherche dans le pool 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 object Ssortingng n’est créé.

    Mais si vous dites:

     Ssortingng a = new Ssortingng("xyz") 

    Vous forcez JVM à créer une nouvelle référence Ssortingng , même si "xyz" trouve dans son pool.

    Pour plus d’informations, lisez ceci .

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

    En Java, ces chaînes littérales sont regroupées en interne et la même instance Ssortingng de "abc" est utilisée chaque fois que vous avez cette chaîne littérale déclarée dans votre code. Donc, "abc" == "abc" sera toujours vrai car ils sont tous deux la même instance de Ssortingng.

    A l’aide de la méthode Ssortingng.intern() , vous pouvez append n’importe quelle chaîne aux chaînes regroupées en interne. Celles-ci seront conservées en mémoire jusqu’à la Ssortingng.intern() Java.

    D’un autre côté, utiliser new Ssortingng("abc") créera un nouvel object ssortingng en mémoire, qui est logiquement le même que le littéral "abc" . "abc" == new Ssortingng("abc") sera toujours faux, car même s’ils sont logiquement égaux, ils se réfèrent à des instances différentes.

    Encapsuler un constructeur Ssortingng autour d’un littéral de chaîne n’a aucune valeur, il utilise inutilement plus de mémoire que nécessaire.

    Ssortingng est une classe en Java différente des autres langages de programmation. Donc, comme pour chaque classe, la déclaration d’object et l’initialisation est

     Ssortingng st1 = new Ssortingng(); 

    ou

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

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

    C’est:

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

    Parce que st1 , st2 , st3 font référence à 3 objects différents, et que == vérifie l’égalité dans l’emplacement de la 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 Ssortingng

     Ssortingng st = "hello"; 

    Ici, la méthode intern() de la classe Ssortingng est appelée, et vérifie si "hello" est dans le pool interne, et sinon, elle est ajoutée au pool interne, et si “hello” existe dans le pool interne, alors st indiquera mémoire du "hello" existant.

    Donc en cas de:

     Ssortingng st3 = "hello"; Ssortingng st4 = "hello"; 

    Ici:

     st3 == st4 // true 

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

    Aussi:

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

    Dans le premier cas, il y a deux objects créés.

    Dans le second cas, c’est juste un.

    Bien que les deux façons str se réfère à "abc" .

    Certains déassemblys sont toujours intéressants …

     $ cat Test.java public class Test { public static void main(Ssortingng... args) { Ssortingng abc = "abc"; Ssortingng def = new Ssortingng("def"); } } $ javap -c -v Test Comstackd 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."":()V const #2 = Ssortingng #17; // abc const #3 = class #18; // java/lang/Ssortingng const #4 = Ssortingng #19; // def const #5 = Method #3.#20; // java/lang/Ssortingng."":(Ljava/lang/Ssortingng;)V const #6 = class #21; // Test const #7 = class #22; // java/lang/Object const #8 = Asciz ; ... { public Test(); ... public static void main(java.lang.Ssortingng[]); Code: Stack=3, Locals=3, Args_size=1 0: ldc #2; // Load ssortingng constant "abc" 2: astore_1 // Store top of stack onto local variable 1 3: new #3; // class java/lang/Ssortingng 6: dup // duplicate top of stack 7: ldc #4; // Load ssortingng constant "def" 9: invokespecial #5; // Invoke constructor 12: astore_2 // Store top of stack onto local variable 2 13: return } 

    En plus des réponses déjà publiées, consultez également cet excellent article sur javaranch.

    Selon la documentation de la classe Ssortingng, ils sont équivalents.

    Documentation pour Ssortingng(Ssortingng original) indique également que: Sauf si une copie explicite de l’original est nécessaire, l’utilisation de ce constructeur n’est pas nécessaire car les chaînes sont immuables.

    Rechercher d’autres réponses, car il semble que la documentation Java est trompeuse 🙁

    Voici quelques comparaisons:

     Ssortingng s1 = "Hello"; Ssortingng s2 = "Hello"; Ssortingng s3 = new Ssortingng("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é, la référence est modifiée.

    Il existe des différences subtiles entre l’object Ssortingng et le littéral de chaîne.

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

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

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

    Dans ce cas, comme nous avons utilisé le new mot-clé, Java créera un nouvel object Ssortingng 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.

    Ssortingng s = new Ssortingng("FFFF") crée 2 objects: la chaîne "FFFF" et l’object Ssortingng , qui pointent vers la chaîne "FFFF" , comme s’il s’agissait d’un pointeur (référence à la référence, je ne suis pas intéressé par la terminologie).

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