Question sur = = opérateur en java


public class Demo {  

    public static void main(String[] args) {

        String s1 = "Hello";
        String s2 = "Hello";
        System.out.println("s1 == s2 " + (s1 == s2));

        String s5 = "Hel" + "lo";
        String s6 = "He" + "llo";
        System.out.println("s5 == s6 " + (s5 == s6));

        String s7 = "He";
        String s8 = "Hello";
        s7 = s7.concat("llo");
        System.out.println("s7 == s8 " + (s7 == s8));

        String s10 = "He";
        s10 = s10 + "llo";
        System.out.println("s1 == s10 "+(s1 == s10));
    }
}

Dans le code précédent s7 == s8 et s1 == s10 donnent false. Quelqu'un peut-il m'expliquer ce qui s'est réellement passé ici dans s7 = s7.concat ("llo"); et s10 = s10 + "llo"; Je comprends == l'opérateur vérifie la référence et equal() vérifie le contenu de l'objet. Mais j'ai besoin de savoir pourquoi les modèles de bits des variables de référence s7 et s10 sont différents de s8 et s1. Si ces choses sont liées aux chaînes générées au moment de la compilation et aux chaînes générées au moment de l'exécution, comment puis-je identifier si c'est le cas chaîne de temps de compilation ou d'exécution?

Author: halfdan, 2010-09-26

7 answers

La raison pour laquelle cela se produit est parce que Java optimise dans le compilateur. Quand il voit que vous attribuez la chaîne littérale "Hello" à s1, il utilise le même "Bonjour" pour s2, car toutes les opérations de chaîne Java sont non destructives (par exemple, elles renvoient un clone plutôt que de modifier l'original), donc c'est une chose sûre à faire.

Même chose pour "Hel" + "lo" vs "He" + "llo"; c'est assez intelligent pour comprendre que c'est la même chose.

Les autres sont suffisamment complexes pour qu'ils ne puissent pas optimiser eux, et ainsi vous vous retrouvez avec des objets séparés.

 11
Author: Clint Tseng, 2010-09-26 19:34:55

== ne vérifie pas les modèles de bits, il comparera l'adresse mémoire des objets. Seulement le même objet a la même adresse mémoire.

 4
Author: Alexander Sagen, 2010-09-26 19:36:47

La réponse de Clint est correcte mais je vais la développer davantage et l'expliquer au niveau du compilateur.

Comme vous le savez, s1 et s2 finiront par être des références à la même instance de chaîne, "Hello".

Pour s5 et s6, le compilateur voit des expressions constantes. C'est, il voit une opération entre deux constantes (les littéraux de chaîne). Le compilateur sait comment ajouter des chaînes et quel serait le résultat. Puisque les valeurs sont connues immédiatement au moment de la compilation, il fait le outre pour vous, résultant dans la chaîne littérale "Hello". Par conséquent, il a la même valeur que s1 et s2 donc chacun fera également référence à la même instance.

s7 ne peut pas être simplifié de la même manière. s7 commence initialement par "He" bien sûr. La différence ici est que s7 = s7.concat("llo"); comme réaffectant s7 au résultat d'un appel de fonction. Cela n'a pas pu être simplifié tel quel. En ce qui concerne le compilateur Java, les résultats de tous les appels de fonction ne sont pas connus au moment de la compilation. Comme il ne connaît pas la valeur résultante, il ne peut pas être simplifié et est laissé tel quel. L'appel résultant renvoie une nouvelle instance d'une chaîne "Hello" qui n'est pas la même instance que l'instance de compilation (que s8 partage).

s10 ne peut pas être simplifié de la même manière. s10 commence initialement par "He" bien sûr. Puis est réaffecté s10 = s10 + "llo"; Cela n'a pas pu être simplifié. Pourquoi me demanderez-vous? Eh bien s10 est une expression de variable non finale. Signification techniquement, l' le compilateur ne connaît pas sa valeur car ce n'est pas une constante. Si s10 a été déclaré a final String, alors cela pourrait être plié constant (lorsqu'il est affecté à une variable différente).

Alors considérez cette version de votre code de test:

public static void main(String[] args)
{
    String s1 = "Hello";
    String s2 = "Hello";
    System.out.println("1: s1 == s2 " + (s1 == s2));    // 1

    String s3 = "Hel" + "lo";
    String s4 = "Hel".concat("lo");
    System.out.println("2: s1 == s3 " + (s1 == s3));    // 2
    System.out.println("3: s1 == s4 " + (s1 == s4));    // 3

    String he = "He";
    String s5 = he + "llo";
    String s6 = he.concat("llo");
    System.out.println("4: s1 == s5 " + (s1 == s5));    // 4
    System.out.println("5: s1 == s6 " + (s1 == s6));    // 5

    final String fhe = "He";
    String s7 = fhe + "llo";
    String s8 = fhe.concat("llo");
    System.out.println("6: s1 == s7 " + (s1 == s7));    // 6
    System.out.println("7: s1 == s8 " + (s1 == s8));    // 7
}

Pouvez-vous déterminer quelles lignes sont vraies?

vrai, vrai, faux, faux, faux, vrai, faux
Vous vous demandez peut-être pourquoi les 3 et 7 ne sont pas vrais. Réponse courte, le compilateur Java n'a pas été programmé
être assez intelligent pour reconnaître l'appel concat () est donc traité comme un appel de fonction régulier.

 4
Author: Jeff Mercado, 2010-09-27 05:35:20

L'opérateur = teste si les références sont les mêmes (c'est à dire pointant vers le même objet), pas si les valeurs de références sont les mêmes. Si vous devez tester si une chaîne est égale à une autre, vous devez utiliser le intégré .méthode equals. Cela fera une comparaison de valeur d'objet. par exemple

final String expectedValue = "Foo";
final String actualValue = "F" + "oo";
if (expectedValue.equals(actualValue)) {
  // This will trigger where == would not
}

De plus, pour des raisons de sécurité, si vous comparez deux chaînes et que l'une est une constante, il est généralement préférable d'invoquer equals sur la constante, c'est-à-dire

String myValue = getMyValue;
boolean theSame = "Some value".equals(myValue);

Plutôt que

String myValue = getMyValue;
boolean theSame = myValue.equals("Some Value");

Le la raison en est que la deuxième forme risque une exception de pointeur null qui peut être évitée en appelant equals() sur la chaîne constante qui est garantie d'être là.

 0
Author: locka, 2010-09-26 19:38:07

Vous ne pouvez pas faire d'hypothèse sur les objets string.

Une machine virtuelle pourrait travailler dur pour s'assurer qu'aucun objet chaîne contenant exactement le même tableau de caractères n'existe en même temps, alors que d'autres machines virtuelles autoriseraient les doublons.

 0
Author: Barthelemy, 2010-09-26 19:38:23

Le == exploitant vérifie si deux objets ont la même adresse (pointeur). Uniquement pour les types primitifs qui ne sont pas une référence (comme int, char, etc.) le fait de comparer la valeur.

Vous devez utiliser quelque chose comme s1.equals(s2) pour comparer le contenu de deux chaînes.

 0
Author: erjiang, 2010-09-26 19:39:31

Dans l'exemple que vous avez fourni, voici ce qui se passe:

String s7 = “He”;    //s7 is an object referencing a part of memory holding “He”
String s8 = “Hello”;   //s8 is an object referencing a part of memory holding “Hello”
s7 = s7.concat(“llo”); //s7.concat(“llo”) created a new object in memory that contains “Hello” and s7 now references this now object 

(s7==s8)             //checks if the equality of the object reference and this is false since they reference different memory addresses.

(s7.equals(s8))         //this will compare s7 and s8 however way the String class compares two String objects. 
 0
Author: Vijay Selvaraj, 2010-09-26 19:59:44