10 votes

Comment Java stocke-t-il les chaînes de caractères et comment les sous-chaînes fonctionnent-elles en interne ?

class StringTesting {
    public static void main(String args[])
    {
        String str = "abcd";
        String str1 = new String("abcd");
        String str2 = str.substring(0,2);
        String str3 = str.substring(0,2);
        String str4 = str.substring(0,str.length());
        String str5 = str1.substring(0,2);
        String str6 = str1.substring(0,2);
        String str7 = str1.substring(0,str1.length());

        System.out.println(str2 == str3);
        System.out.println(str == str4);
        System.out.println(str5 == str6);
        System.out.println(str1 == str7);
    }
}

Voici le résultat que j'obtiens avec java 1.6.0_27 :

false
true
false
true

Quelqu'un peut-il expliquer le résultat ? Je sais que Java fait la différence entre les chaînes stockées dans le tas et les chaînes stockées dans le "pool commun" des chaînes (qui peut être internalisé). En interne, en quoi leur représentation est-elle différente ? En quoi cela modifie-t-il l'algorithme de sous-chaîne. Veuillez citer le livre, l'article, le blog, etc. dans la mesure du possible.

22voto

assylias Points 102015

Voir les commentaires :

    String str = "abcd";  // new String LITERAL which is interned in the pool
    String str1 = new String("abcd"); // new String, not interned: str1 != str
    String str2 = str.substring(0,2); // new String which is a view on str
    String str3 = str.substring(0,2); // same: str3 != str2
    String str7 = str1.substring(0,str1.length()); // special case: str1 is returned

Notes :

  • Depuis Java 7u6, substring renvoie une nouvelle chaîne au lieu d'une vue sur la chaîne originale (mais cela ne fait pas de différence pour cet exemple).
  • Cas particulier lorsque vous appelez str1.substring(0,str1.length()); - voir le code :

    public String substring(int beginIndex, int endIndex) {
        //some exception checking then
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }

EDIT

Qu'est-ce qu'une vue ?

Jusqu'à la version 7u6 de Java, une chaîne de caractères était en fait une char[] qui contient les caractères de la chaîne avec un décalage et un décompte (c'est-à-dire que la chaîne est composée de count caractères à partir du offset dans le cadre de la char[] ).

Lors de l'appel à substring, une nouvelle chaîne est créée avec la même valeur de char[] mais avec un décalage / comptage différent, afin de créer une vue sur la chaîne originale. (Sauf lorsque count = length et offset = 0 comme expliqué ci-dessus).

Depuis Java 7u6, un nouveau char[] est créé à chaque fois, car il n'y a plus de count o offset dans la classe des chaînes de caractères.

Où se trouve exactement la piscine commune ?

Il s'agit d'une mise en œuvre spécifique. L'emplacement du pool a en fait changé dans les versions récentes. Dans les versions les plus récentes, il est stocké sur le tas.

Comment la piscine est-elle gérée ?

Caractéristiques principales :

  • Les chaînes de caractères littérales sont stockées dans le pool
  • Les chaînes internes sont stockées dans le pool ( new String("abc").intern(); )
  • Lorsqu'une chaîne de caractères S est interné (parce que c'est un littéral ou parce que intern() est appelée), la JVM renverra une référence à une chaîne de caractères dans le pool s'il y en a une qui est equals a S (d'où "abc" == "abc" doit toujours renvoyer la valeur "true").
  • Les chaînes dans le pool peuvent être collectées (ce qui signifie qu'une chaîne internée peut être retirée du pool à un moment donné s'il devient plein).

2voto

Subhrajyoti Majumder Points 20001

String est un objet immuable.

String#subString - crée une nouvelle chaîne . Source

Dans le code, c'est [open jdk 6] -

 public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > value.length) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    int subLen = endIndex - beginIndex;
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return ((beginIndex == 0) && (endIndex == value.length)) ? this
            : new String(value, beginIndex, subLen);
}

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