web-dev-qa-db-fra.com

String s = new String ("xyz"). Combien d'objets a été créé après l'exécution de cette ligne de code?

La réponse commune à cette question d’entrevue est que le code crée deux objets. Mais je ne le pense pas J'ai écrit du code pour confirmer.

public class StringTest {
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = "a";
        String s3 = new String("a");
        System.out.println("s1: "+s1.hashCode());
        System.out.println("s2: "+s2.hashCode());
        System.out.println("s3: "+s3.hashCode());
    }
}

La sortie est:

Application output

Cela signifie-t-il qu'un seul objet a été créé?

Réaffirmez: Ma question est de savoir combien d'objets ont été créés avec le code suivant:

String s = new String("xyz")

Au lieu du code StringTest.

Inspiré par @Don Branson, j'ai débogué le code ci-dessous:

public class test {
    public static void main(String[] args) {
        String s = new String("abc");
    }
}

Et le résultat est:

Enter image description here

L'identifiant de s est 84 et l'identifiant de "abc" est 82. Qu'est-ce que cela signifie exactement?

22
smileVann

IL Y A DES ERREURS CI-DESSOUS SELON LA JVM/JRE QUE VOUS UTILISEZ. C'EST IS MIEUX DE NE PAS ÊTRE SOUCIEUX DE CHOSES QUI NE SONT EN AUCUN CAS. VOIR LA SECTION DES COMMENTAIRES POUR LES CORRECTIONS/PRÉOCCUPATIONS.

Tout d’abord, cette question concerne réellement le sujet abordé ici: Est-ce que String Literal Pool est une collection de références à l’objet String, ou une collection d’objets

C'est donc un guide pour tout le monde sur cette question.

...

Étant donné cette ligne de code: String s = new String(“xyz”)

Il y a deux façons de voir cela:

(1) Que se passe-t-il lorsque la ligne de code s'exécute - le moment littéral où elle s'exécute dans le programme?

(2) Quel est l’effet net de combien de Objects sont créés par la déclaration?

Réponse:

1) Après cela, s'exécute, un objet supplémentaire est créé.

a) Le "xyz"String est créé et interné lorsque la JVM charge le class dans lequel cette ligne de code est contenue.

  • Si un "xyz" est déjà dans le pool interne à partir d'un autre code, le littéral peut ne générer aucun nouvel objet String.

b) Lorsque le nouveau String s est créé, le char[] interne est une copie de la chaîne interned"xyz".

c) Cela signifie que, lorsque la ligne exécute, un seul objet supplémentaire est créé. 

Le fait est que l’objet "xyz" aura été créé dès le chargement de la classe et avant l’exécution de cette section de code.

... scénario suivant ...

2) Il y a trois objets créés par le code (y compris le "a" interné)

String s1 = "a";
String s2 = "a";
String s3 = new String("a");

a) s1 et s2 sont simplement référencés, pas des objets, et ils pointent vers le même String en mémoire.

b) Le "a" est interné et est un objet composé: un objet char[] et l'objet String lui-même. Il consiste en deux objets en mémoire.

c) s3, new String("a") génère un objet de plus. Le nouveau String("a") ne copie pas le char[] de "a", il le référence uniquement en interne. Voici la signature de la méthode:

public String2(String original) {
        this.value = original.value;
        this.hash = original.hash;
}

Un String("a") interné est égal à 2 Objects. Et un new String("a") équivaut à un autre objet. L'effet net du code est trois objets.

19
The Coordinator

Deux objets seront créés pour cela:

String s = new String("abc");

Un dans le tas et l'autre dans le "string constant pool" (SCP). La référence s désignant toujours s et GC n'étant pas autorisé dans la zone SCP, tous les objets situés sur SCP seront automatiquement détruits au moment de l'arrêt de la JVM.

Par exemple:

Ici, en utilisant une référence d'objet de tas, nous obtenons la référence d'objet SCP correspondante par appel de intern ()

String s1 = new String("abc");
String s2 = s1.intern(); // SCP object reference
System.out.println(s1==s2); // false
String s3 = "abc";
System.out.println(s2==s3); //True s3 reference to SCP object here
8
user2663609

Il existe deux manières de créer des objets chaîne en Java:

  1. En utilisant le nouvel opérateur, c.-à-d.

    String s1 = new String("abc");
    
  2. En utilisant un littéral de chaîne, c'est-à-dire.

    String s2 = "abc";
    

L'allocation de chaînes étant coûteuse en temps et en mémoire, la JVM (Java Virtual Machine) effectue certaines tâches. QUELLES TACHES? 

Voir, chaque fois que vous utilisez l'opérateur new, l'objet est créé et la machine virtuelle Java ne recherche pas dans le pool de chaînes. Il ne fait que créer l'objet, mais lorsque vous utilisez les littéraux de chaîne pour créer des objets chaîne, la machine virtuelle Java effectue la tâche de recherche dans le pool de chaînes. 

C'est à dire quand vous écrivez

String s2 = "abc";

la machine virtuelle Java recherchera dans le pool de chaînes et vérifiera si "abc" existe déjà ou non. S'il existe, une référence à la chaîne "abc" existante est renvoyée. Aucun nouvel objet n'est créé. S'il n'existe pas, un objet est créé.

Donc dans votre cas (A)

String s1 = new String("abc");
  • Puisque new est utilisé, l'objet est créé

(b)

String s2 = "abc";
  • en utilisant un littéral de chaîne, un objet est créé et "abc" ne figure pas dans le pool string et par conséquent, l'objet est créé.

(c)

String s2 = "abc";
  • Encore une fois en utilisant un littéral de chaîne et "abc" est dans le pool de chaînes, et Par conséquent, l'objet n'est pas créé.

Vous pouvez également le vérifier en utilisant le code suivant:

class String_Check
{
    public static void main(String[] n)
    {
        String s1 = new String("abc");
        String s2 = "abc";
        String s3 = "abc";
        if (s1==s2)
            System.out.println("s1==s2");
        if(s1==s3)
            System.out.println("s1==s3");
        if(s2==s3)
            System.out.println("s2==s3");
    }
}

J'espère que cela aide ... Notez que == est utilisé pour voir si les objets sont égaux et la méthode equals(Object) est utilisée pour voir si le contenu est égal.

4
Musaddique

Si nous exécutons String s = new String("Brajesh");, deux objets doivent être créés. Un objet sera créé dans le pool de littéraux de chaîne et un autre dans la zone de segment de mémoire . Mais si nous avons déjà le même objet littéral de chaîne, un seul objet est créé . 

String s1  ="Brajesh"; 
String s = new String("Brajesh");//it will create only one object in heap area

En plus de cela, un objet supplémentaire est également créé dans la zone de tas qui est l'objet de char []. J'ai joint ici un instantané de la mémoire heap .  enter image description here

2
Brajesh

2 ou 3 objets sont créés, en fonction de l'intelligence du compilateur.

Néanmoins, votre test est indésirable, car hashCode sur Strings est basé sur le contenu de String et non sur son identité. Si vous souhaitez vérifier l'identité, vous devez utiliser System.identityHashCode ou simplement == comparaison.

Le compilateur et le runtime sont autorisés (pas forcés) à optimiser la création de chaînes autant que possible. Donc, ils optimisent les chaînes littérales, en utilisant un seul littéral pour les trois chaînes que vous avez . Quoi qu'il en soit, l'opérateur newdoit renvoyer un objet nouveau (c'est-à-dire un nouvel attribut). L’optimisation des chaînes au moment de l’exécution est possible si la méthode statique String.valueOf est utilisée à la place. Mais je ne sais pas si la mise en cache est réellement appliquée par les JRE actuels (peut-être est-il plus coûteux de vérifier une table de hachage que d’allouer un nouveau String)

1
Giulio Franco

Si new String () crée 2 objets (un dans le tas et un dans le pool String), quelle est l'utilisation de la méthode .intern?

la méthode intern () invoquée sur un objet String cherche la chaîne contenu par cet objet String dans le pool, si la chaîne est trouvée la chaîne de la piscine est alors renvoyée. Sinon, ceci L'objet String est ajouté au pool et une référence à cette chaîne l'objet est retourné.

0
Rahul

Si nous exécutons le code ci-dessous dans Eclipse en mode débogage, nous aurons une idée du nombre d'objets créés avec String string = new String("manoj");. En interne, il créera le constructeur String str = "manoj"in String. Il suffit de vérifier id après avoir survolé la référence, comme indiqué dans la capture d'écran ci-dessous . ScreenShot

public static void main(String[] args)
{
    String str = "atul";
    String string = new String("manoj");
    String string2 = "manoj";
    System.out.println(str == string);
}
0
atul_java
public String(String original) {
    int size = original.count;
    char[] originalValue = original.value;
    char[] v;
    if (originalValue.length > size) {
        // The array representing the String is bigger than the new
        // String itself.  Perhaps this constructor is being called
        // in order to trim the baggage, so make a copy of the array.
        int off = original.offset;
        v = Arrays.copyOfRange(originalValue, off, off+size);
    } else {
        // The array representing the String is the same
        // size as the String, so no point in making a copy.
        v = originalValue;
    }
    this.offset = 0;
    this.count = size;
    this.value = v;
}

Si nous voyons le code, nous pouvons voir qu'il va simplement créer un caractère [] et qu'il sera copié à chaque fois avec le même contenu, instancié et oui, il stockera les données dans le pool String Constant. 1) Prendra de SCP Chaîne s1 = "a" Chaîne s2 = "a"; 2) crée un nouvel objet String s3 = new String ("a"); Curiosité, nouvel objet String s2 = new String ("a"); En tout code ci-dessus même char [] sera copié.i: e char [] valeurVous pouvez vérifier ici

0
Samrat Roy
        String s1="Pune";
        String s2="Mumbai";
        String s3="Pune";
        String s4=new String("Mumbai");
        System.out.println("S1 :"+s1.hashCode());  //S1 :2499228
        System.out.println("S2 :"+s2.hashCode());  //S2 :-1979126203
        System.out.println("S3 :"+s3.hashCode());  //S3 :2499228
        System.out.println("S4 :"+s4.hashCode());  //S4 :-1979126203
        System.out.println(s2==s4);     // false

Comme nous pouvons le voir dans le programme ci-dessus, nous obtenons un hashcode similaire pour s2 et s4 respectivement, bien que nous obtenions false avec l'opérateur ==. L'opérateur == est utilisé pour la comparaison de référence. 

Deux objets ont été créés à "String s4 = new String (" Mumbai ")", un dans la mémoire de tas et un dans la mémoire de pile. Par conséquent, s2 compare avec s4 qui est créé dans la mémoire de tas, pas avec la mémoire de pile.

0
Kiran Kawade

Java.lang.String remplace la méthode hashCode() de sorte que la valeur dépend du contenu de la chaîne. 

Par conséquent, hashCode() ne vous dit rien du nombre d'instances. Il peut s'agir de la même chaîne ou d'une autre instance sans octet unique partagé. Idem à propos de equals(). Cela explique votre sortie.

Utilisez System.identityHashCode (..) pour ce type de recherche. 

Et que la source soit avec vous .

0
h22

Confondu avec ce qui se passe exactement après l'appel de la nouvelle chaîne ("<>"), j'ai trouvé ce fil. Votre compréhension de la comparaison du hashcode n’est pas techniquement correcte.

int hashCode () a été remplacé dans la classe String et renvoie une valeur en fonction du contenu du littéral String.

Chaîne s1 = nouvelle chaîne ("Bonjour"); Chaîne s2 = nouvelle chaîne ("Bonjour");

Donc, s1.hashCode () = s2.hashCode () = anyStringOfContent_ "Hello" .hashCode ()

**/** Cache the hash code for the string */
private int hash; // Default to 0
public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;
        for (int i = 0; i < value.length; i++) {
            **h = 31 * h + val[i];**
        }
        hash = h;
    }
    return h;
}**

Maintenant, juste pour expliquer pourquoi cela est fait, vous pouvez en fait lire le livre de Kathy Sierra, qui explique en grande partie pourquoi les développeurs l’ont fait de cette manière (en principe, tout objet renvoyant la méthode true à equals () devrait renvoyer la même valeur hashCode ()).

0
Priyak Dey