2010-06-12 8 views
9

Par exempleLes chaînes créées avec + concaténation sont-elles stockées dans le pool de chaînes?

String s = "Hello" + " World"; 

Je sais qu'il ya deux chaînes dans la piscine « Bonjour » et « World », mais, fait: « Bonjour tout le monde » aller dans la piscine de chaîne?

Si oui, et pourquoi?

String s2 = new String("Hola") + new String(" Mundo"); 

Combien de chaînes y a-t-il dans le pool?

+0

" String pool ", ou voulez-vous dire le pool constant? –

+0

J'imagine qu'il veut dire que le pool String est défini comme le pool constant – danben

+0

mmmhh J'ai dit "pool de chaînes" parce que c'est comme ça que c'est référencé par String.intern() doc * .. Un pool de chaînes, initialement vide ... * (http://java.sun.com/javase /6/docs/api/java/lang/String.html#intern%28%29) Mais, je ne suis pas sûr si cela devrait être appelé "pool constant" .Est-ce que cela devrait? – OscarRyz

Répondre

4

je crois dans le premier cas, le compilateur sera intelligent et mettre la chaîne concaténée dans la piscine (vous aurez seulement 1 chaîne y)

+0

Est-il vrai que dans le second cas, puisqu'il n'y a pas de référence pour les littéraux, l'objet dans le pool est éligible pour le garbage collection et donc dans le second cas il n'y aura aucun objet dans le pool de chaînes? – OscarRyz

+0

@Support - no. Dans le second cas, l'entrée du pool sans chaîne est créée ... mais pas pour les raisons que vous avez données. L'éligibilité pour la récupération de place n'a rien à voir avec l'internement implicite. (En effet, pour les JVM modernes, la chaîne dans le pool String * peut être * garbage collectée, s'ils ne sont pas joignables via une autre route.) –

10

Oui, si un String est formé par deux concaténer Stringlittéraux il sera également interné.

De l'JLS:

Ainsi, le programme de test constitué par l'unité de compilation (§7.3):

package testPackage; 
class Test { 
    public static void main(String[] args) { 
     String hello = "Hello", lo = "lo"; 
     System.out.print((hello == "Hello") + " "); 
     System.out.print((Other.hello == hello) + " "); 
     System.out.print((other.Other.hello == hello) + " "); 
     System.out.print((hello == ("Hel"+"lo")) + " "); 
     System.out.print((hello == ("Hel"+lo)) + " "); 
     System.out.println(hello == ("Hel"+lo).intern()); 
    } 
} 
class Other { static String hello = "Hello"; } 
and the compilation unit: 
package other; 
public class Other { static String hello = "Hello"; } 

produit la sortie:

true 
true 
true 
true 
false 
true 

Les lignes importantes sont 4 et 5. 4 représente ce que vous demandez dans le f premier cas; 5 vous montre ce qui se passe si l'on n'est pas littéral (ou plus généralement, une constante de compilation).

+0

... aaet combien de chaînes y a-t-il dans le pool? :) – OscarRyz

+0

3 dans le premier cas puisque 3 choses ont été internées ("Bonjour", "monde", et "Bonjour tout le monde"). Dans le second cas, vous n'avez que deux littéraux, donc 2. – danben

+3

dans le premier cas il n'y a qu'un seul littéral String car le compilateur a opté pour les deux premiers. Si vous regardez le fichier de classe compiles, il n'y a qu'un seul littéral String. –

1

en confirmant la réponse de Agnew @ Brian, je regardais ce code:

public class InternTest { 
    public static void main(String[] args) { 
     String s = "Hello" + ", world"; 
     System.out.println(s); 
    } 
} 

Ce comportement est requis pour string literals et constant expressions qui évaluent à un String.

 
javap -c InternTest 
Compiled from "InternTest.java" 
public class InternTest extends java.lang.Object{ 
public InternTest(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: ldC#2; //String Hello, world 
    2: astore_1 
    3: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 
    6: aload_1 
    7: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    10: return 
+0

Non, c'est obligatoire. –

-2

Non. Seuls les littéraux de chaîne sont requis pour entrer dans le pool. Les compilateurs peuvent optimiser la concaténation et peuvent stocker des littéraux de chaîne supplémentaires dans le pool.

+0

Donc, * Combien de chaînes y a-t-il dans la piscine? * – OscarRyz

+0

Non, c'est obligatoire. –

-1
String hello = "Hello", lo = "lo";  
// known at compile time so created in String constant pool 

System.out.print((hello == "Hello") + " "); 
// known at compile time so "Hello" is same object as in hello 

System.out.print((Other.hello == hello) + " "); 
// Other.hello and hello created at compile time so referenced to same object 

System.out.print((other.Other.hello == hello) + " "); 
// other.Other.hello and hello created at compile time 
// so referenced to same object 

System.out.print((hello == ("Hel"+"lo")) + " "); 
// hello and "Hel"+"lo" both were created at compile 
// time so referenced to same object 

System.out.print((hello == ("Hel"+lo)) + " "); 
// value in lo was not known in runtime so didn't 
// referenced to object in hello, instead created new object in String Pool Constant 

System.out.println(hello == ("Hel"+lo).intern()); 
// ("Hel"+lo).intern() using intern function told at runtime 
// to check weather same string present in String Constant Pool, 
// and if present then reference to the same string which was already present in String Constant Pool. 
0

Si je me trompe, corrigez-moi. Selon ma compréhension, un seul objet va être créé dans SCP. As String s = "Bonjour" + "Monde"; est une constante de temps de compilation. Le compilateur ajoutera ces deux chaînes au moment de la compilation seulement. Et un seul objet sera créé dans SCP. Si vous ouvrez et voyez le fichier .class, vous trouverez "HelloWorld dans le fichier .class

+2

C'est exactement ce que la réponse existante dit déjà, oui. – Tom