2011-08-17 2 views
1

Comment fonctionnent les objets String en Java? Comment le terme "immuable" s'applique-t-il exactement aux objets string? Pourquoi ne voyons-nous pas une chaîne modifiée après avoir traversé une méthode, bien que nous opérions sur la valeur originale de l'objet chaîne?Cordes - Comment fonctionnent-elles?

+0

duplication possible de [Pourquoi les chaînes ne peuvent-elles pas être modifiées en Java et .NET?] (http://stackoverflow.com/questions/93091/why-cant-strings- be-mutable-in-java-and-net) – adatapost

+4

Comment cette question en 3 parties mal documentée a-t-elle été mise à jour? * "Explication avec des exemples est appréciée." * Oui (sèchement) comme sont des questions bien étudiées. –

+0

Andrew ..! Mes excuses ! –

Répondre

10

une chaîne a une finale privée char[]. Lorsqu'un nouvel objet String est créé, le tableau est également créé et rempli. il ne peut pas être accédé plus tard [de l'extérieur] ou modifié [en fait il peut être fait avec la réflexion, mais nous laisserons cela de côté].

est "immuable" car une fois qu'une chaîne est créée, sa valeur ne peut pas être changée, une chaîne "vache" aura toujours la valeur "vache".

Nous ne voyons pas de chaîne modifiée car elle est immuable, le même objet ne sera jamais modifié, peu importe ce que vous en ferez [en plus de le modifier avec la réflexion]. donc "vache" + "cheval" va créer un nouvel objet String , et ne pas modifier le dernier objet.

si vous définissez:

void foo(String arg) { 
    arg= arg + " horse"; 
} 

et que vous appelez:

String str = "cow"; 
foo(str); 

le str où l'appel est est pas modifié [car il est la référence originale au même objet!] Lorsque vous arg modifié, vous l'avez simplement modifié pour référencer un autre objet String et vous n'avez PAS modifié l'objet original. donc str, sera le même objet, qui n'a pas été modifié, contenant encore "cow"

si vous voulez toujours changer un objet String, vous pouvez le faire avec la réflexion.Cependant, il est unadvised et peut avoir un sérieux côté affecte:

String str = "cow"; 
    try { 
    Field value = str.getClass().getDeclaredField("value"); 
    Field count = str.getClass().getDeclaredField("count"); 
    Field hash = str.getClass().getDeclaredField("hash"); 
    Field offset = str.getClass().getDeclaredField("offset"); 
    value.setAccessible(true); 
    count.setAccessible(true); 
    hash.setAccessible(true); 
    offset.setAccessible(true); 
    char[] newVal = { 'c','o','w',' ','h','o','r','s','e' }; 
    value.set(str,newVal); 
    count.set(str,newVal.length); 
    hash.set(str,0); 
    offset.set(str,0); 
    } catch (NoSuchFieldException e) { 
    } catch (IllegalAccessException e) {} 
    System.out.println(str); 
} 
+0

+1 pour l'exemple – Charliemops

+0

L'utilisation de cow comme exemple pour votre chaîne devient confuse lors de la recherche de C.O.W copy sur write Java Strings. https://en.wikipedia.org/wiki/Immutable_object#Copy-on-write – masters3d

4

De l'tutorial:

La classe String est immuable, de sorte qu'une fois qu'il est créé un objet String ne peut pas être changé. La classe String a un certain nombre de méthodes, dont certaines seront abordées ci-dessous, qui semblent modifier les chaînes. Puisque les chaînes sont immuables, ce que ces méthodes font vraiment, c'est créer et retourner une nouvelle chaîne qui contient le résultat de l'opération.

2

Les chaînes de Java sont immuables (l'état ne peut pas être modifié une fois créé). Cela offre des opportunités d'optimisation. Un exemple est l'internement de chaîne, où les littéraux de chaîne sont conservés dans un pool de chaînes et les nouveaux objets String sont créés uniquement si le littéral de chaîne particulier n'existe pas déjà dans le pool. Si le littéral de chaîne existe déjà, une référence est renvoyée. Cela ne peut être accompli que parce que les chaînes sont immuables, donc vous n'avez pas à vous inquiéter qu'un objet contenant une référence le change.

Les méthodes qui semblent modifier une chaîne renvoient en réalité une nouvelle instance. Un exemple est la concaténation de chaîne:

String s = ""; 
for(int i = 0; i < 5; i++){ 
    s = s + "hi"; 
} 

Qu'est-ce qui se passe réellement en interne (le compilateur, il change):

String s = ""; 
for(int i = 0; i < 5; i++){ 
    StringBuffer sb = new StringBuffer(); 
    sb.append(s); 
    sb.append("hi"); 
    s = sb.toString(); 
} 

Vous pouvez clairement voir que les nouvelles instances sont créées par la méthode toString (notez que cela peut être rendu plus efficace en utilisant directement StringBuffers). Les StringBuffers sont mutables, contrairement aux Strings.

+0

'sb.append (" hi ")' Le "hi" de l'instruction ci-dessus est-il ajouté au pool de chaînes? –

0

Chaque objet a état. L'état d'un objet String est le tableau de caractères qui composent la chaîne, par exemple, la chaîne "foo" contient le tableau ['f', 'o', 'o']. Parce qu'une chaîne est immutable, ce tableau peut jamais être modifié de quelque manière, forme ou forme.

Chaque méthode de chaque classe qui souhaite modifier une chaîne doit à la place renvoyer une nouvelle chaîne qui représente l'état modifié de l'ancienne chaîne. C'est-à-dire, si vous essayez d'inverser "foo" vous obtiendrez un new objet String avec l'état interne ['o', 'o', 'f'].

0

Je pense que this lien vous aidera à comprendre comment String Java fonctionne vraiment

considèrent maintenant le code suivant -

String s = "ABC"; s.toLowerCase(); La méthode toLowerCase() ne changera pas les données « ABC » que l'art contient . Au lieu de cela, un nouvel objet String est instancié et reçoit les données "abc" lors de sa construction. Une référence à cet objet String est renvoyée par la méthode toLowerCase(). Pour que les chaînes contiennent les données "abc", une approche différente est nécessaire.

Encore une fois étudier ce qui suit - s = s.toLowerCase();

Maintenant, les références de la chaîne un nouvel objet String qui contient "abc". Il n'y a rien dans la syntaxe de la déclaration de la classe String qui l'impose comme immuable; plutôt, aucune des méthodes de la classe String n'affecte les données contenues dans un objet String, ce qui le rend immuable.

Je n'ai pas vraiment compris votre troisième question. Peut fournir un morceau de code et dire que votre problème est une meilleure option. J'espère que cela t'aides.

Vous pouvez également regarder dans ce blogpost pour plus de compréhension

[exemples de code sont prises à partir du wiki. vous pouvez également regarder là-dedans pour plus d'informations]