2017-07-18 3 views
3

Question 1concaténation chaîne java et interner

String a1 = "I Love" + " Java"; 
String a2 = "I Love " + "Java"; 
System.out.println(a1 == a2); // true 

String b1 = "I Love"; 
b1 += " Java"; 
String b2 = "I Love "; 
b2 += "Java"; 
System.out.println(b1 == b2); // false 

Dans le premier cas, je comprends que c'est une concaténation de deux chaînes littérales, de sorte que le résultat «J'aime Java » sera interné, donnant le résultat vrai . Cependant, je ne suis pas sûr du second cas.

Question 2

String a1 = "I Love" + " Java"; // line 1 
String a2 = "I Love " + "Java"; // line 2 

String b1 = "I Love"; 
b1 += " Java"; 
String b2 = "I Love "; 
b2 += "Java"; 
String b3 = b1.intern(); 
System.out.println(b1 == b3); // false 

Les rendements supérieurs faux, mais si je commente les lignes 1 et 2, il retourne vrai. Pourquoi donc?

+2

Nous ne comparons jamais vraiment les chaînes en utilisant l'opérateur == et utilisons la méthode .equals à la place –

+1

@JoeyPinto OP utilise '==' pour en savoir plus sur les Java internes, découvrant un comportement qui semble assez étrange, mais qui a une explication raisonnable. – dasblinkenlight

Répondre

4

La première partie de votre question est simple: compilateur Java traite concaténation de littéraux de chaînes multiples en une seule chaîne littérale, soit

"I Love" + " Java" 

et

"I Love Java" 

sont deux chaînes identiques littéraux, qui être correctement interné.

Le même comportement ne interner pas appliquent à += opération sur les chaînes, si b1 et b2 sont effectivement construits au moment de l'exécution.

La deuxième partie est plus délicate. Rappelons que b1.intern() peut renvoyer b1 ou un autre objet String qui lui est égal. Lorsque vous gardez a1 et a2, vous obtenez a1 retour de l'appel à b1.intern(). Lorsque vous commentez a1 et a2, il n'existe aucune copie existante à renvoyer, donc b1.intern() vous renvoie b1 lui-même.

+0

Je pense que je comprends maintenant. Merci @dasblinkenlight! – wli75

1

De stagiaire() docs

Toutes les chaînes littérales et des expressions constantes de type chaîne sont internées. Les littéraux de chaîne sont définis dans la section 3.10.5 de la spécification de langage Java.

Et de JLS 3.10.5

  • Cordes calculées par des expressions constantes (§15.28) sont calculées à de compilation, puis traitées comme si elles étaient littérales.
    • Les chaînes calculées par concaténation à l'exécution sont nouvellement créées et donc distinctes.

Votre chaîne b1 pas réellement interné. D'où la différence.

+0

Merci de m'avoir indiqué la documentation correspondante! – wli75

0

réponse pour la question 1:

Vous ne pouvez pas comparer deux cordes avec ==.Le == compare deux types de données primitifs (int, long, float, double et booléen) ou l'objet références. Ce qui signifie que si les références varibales (a1, a2, b1, b2) n'ont pas la même référence (signifiant qu'elles ne pointent pas sur le même objet en mémoire), elles ne sont pas égales (comparaison avec ==).

Si vous comparez avec b1.equals(b2), l'expression serait vraie puisque les données de l'objet sont les mêmes. Dans le premier cas, Java est assez intelligent pour concaténer les chaînes avant de leur allouer de la mémoire (avant même la compilation), ce qui signifie que les deux chaînes sont stockées à la même adresse. Par conséquent, les variables a1 et a2 font référence au même objet et sont égales (==). Dans le second cas, vous attribuez d'abord une valeur différente aux variables (contrairement au premier cas). Cela signifie qu'ils obtiennent une adresse distincte dans la mémoire. Même si vous modifiez la valeur afin qu'ils soient identiques, l'adresse ne change pas et une comparaison avec == est évaluée à false. Cela se produit pendant l'exécution. En ce qui concerne la question 2: @dasblinkenlight a déjà donné une bonne réponse à cette question.