72 votes

Comportement étrange de piscine String

J’ai une question d’un comportement étrange de piscine String. J’utilise `` pour comparer des chaînes égales pour savoir si elles sont dans la piscine ou non.

Le résultat est :

qui est une grosse surprise pour moi. Quelqu'un pourrait m’expliquer cette s’il vous plaît ? Je pense que quelque chose se déroule dans le temps de compilation. Mais pourquoi fait ajouter `` en String fait une différence du tout ?

110voto

Marko Topolnik Points 77257
"555" + ""

est une constante à la compilation, alors que

giveLiteralString() + ""

n'est-ce pas. Par conséquent, l'ancien compile simplement la chaîne de caractères constante "555", et le second compile dans la méthode d'invocation et la concaténation, résultant en une nouvelle instance de Chaîne.


Voir aussi JLS §3.10.5 (Littéraux de Chaîne):

Les chaînes calculée par concaténation au moment de l'exécution sont nouvellement créé et donc distinctes.

31voto

Evgeniy Dorofeev Points 52031

Après la décompilation cette ligne

System.out.println("555" == "555" + "");

J'ai eu ce bytecode

    LINENUMBER 8 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ICONST_1
    INVOKEVIRTUAL java/io/PrintStream.println(Z)V
    ...

ce qui est équivalent à

  System.out.println(true);

que signifie l'expression "555" == "555" + "" compile boolean true.

Pour giveLiteralString() == giveLiteralString() + "" javac construit ce bytecode

    LINENUMBER 8 L0
    INVOKESTATIC Test1.giveLiteralString()Ljava/lang/String;
    NEW java/lang/StringBuilder
    DUP
    INVOKESTATIC Test1.giveLiteralString()Ljava/lang/String;
    INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
    INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
    IF_ACMPNE L1
    ...

ce qui est équivalent à

if (giveLiteralString() == new StringBuilder(giveLiteralString()).append("").toString()) {
...

qui sera toujours produire des faux car ici nous sommes en comparant 2 disctinct objets.

4voto

Hot Licks Points 25075

Dans le second cas, le compilateur POURRAIT avoir reconnu qu' + "" est un no-op de toutes sortes, depuis "" est au moment de la compilation de la valeur connue à être de longueur zéro. Mais le compilateur est toujours nécessaire de vérifier le résultat de l' giveLiteralString de la valeur null (depuis le nul de la vérification se produisent à la suite de l' + exploitation dans le non-optimisé cas), il est donc plus simple de tout simplement ne pas tenter l'optimisation.

En conséquence, le compilateur génère du code pour effectuer la concaténation, et une nouvelle chaîne est créé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X