Qu'entend-on par immuable?
ce pourrait être la question la plus stupide jamais posée, mais je pense que c'est une confusion totale pour un débutant.
- quelqu'un peut-il préciser ce qu'on entend par immuable ?
- pourquoi un
String
est-il immuable? - Quels sont les avantages/inconvénients des objets immuables?
- pourquoi un objet mutable tel que
StringBuilder
devrait-il être préféré à la corde et au vice-vers?
un bel exemple (en Java) sera vraiment apprécié.
18 réponses
immuable signifie qu'une fois que le constructeur d'un objet a terminé l'exécution, cette instance ne peut pas être modifiée.
C'est utile, car cela signifie que vous pouvez passer des références à l'objet, sans se soucier que quelqu'un d'autre va modifier son contenu. surtout quand il s'agit de simultanéité, il n'y a aucun problème de verrouillage avec les objets qui ne changent jamais
par exemple
class Foo
{
private final String myvar;
public Foo(final String initialValue)
{
this.myvar = initialValue;
}
public String getValue()
{
return this.myvar;
}
}
Foo
n'a pas à s'inquiéter que l'appelant à getValue()
pourrait changer le texte dans la chaîne.
si vous imaginez une classe similaire à Foo
, mais avec un StringBuilder
plutôt qu'un String
comme membre, vous pouvez voir qu'un appelant à getValue()
serait en mesure de modifier l'attribut StringBuilder
d'une instance Foo
.
méfiez-vous également des différents types d'immutabilité que vous pourriez trouver: Eric Lippert a écrit un article de blog à ce sujet. Fondamentalement, vous pouvez avoir des objets dont l'interface est immuable, mais dans les coulisses l'état réel mutable privé (et ne peut donc pas être partagé en toute sécurité entre les fils).
un objet immuable est un objet où les champs internes (ou du moins tous les champs internes qui affectent son comportement externe) ne peuvent pas être changés.
il y a beaucoup d'avantages aux cordes immuables:
Performance: Prendre de l'opération suivante:
String substring = fullstring.substring(x,y);
le C sous-jacent pour la méthode substring () est probablement quelque chose comme ceci:
// Assume string is stored like this:
struct String { char* characters; unsigned int length; };
// Passing pointers because Java is pass-by-reference
struct String* substring(struct String* in, unsigned int begin, unsigned int end)
{
struct String* out = malloc(sizeof(struct String));
out->characters = in->characters + begin;
out->length = end - begin;
return out;
}
notez que aucun des caractères ne doit être copié! si l'objet String était mutable (les caractères pourraient changer plus tard) alors vous auriez à copier tous les caractères, sinon les changements aux caractères dans la chaîne seraient reflétés dans l'autre chaîne plus tard.
simultanéité: si la structure interne d'un objet immuable est valide, elle le sera toujours. Il n'y a aucune chance que les différents les threads peuvent créer un état invalide dans cet objet. Par conséquent, les objets immuables sont Thread Safe .
collecte des ordures: il est beaucoup plus facile pour le collecteur des ordures de prendre des décisions logiques sur les objets immuables.
cependant, il y a aussi des inconvénients à l'immuabilité:
Performance: Attendez, je pensais que vous aviez dit que la performance était un avantage de l'immutabilité! Eh bien, il est parfois, mais pas toujours. Prendre le code suivant:
foo = foo.substring(0,4) + "a" + foo.substring(5); // foo is a String
bar.replace(4,5,"a"); // bar is a StringBuilder
les deux lignes remplacent le quatrième caractère par la lettre"A". Non seulement le deuxième morceau de code est plus lisible, il est plus rapide. Regardez comment vous devriez faire le code sous-jacent pour foo. Les sous-couches sont faciles, mais maintenant, parce qu'il y a déjà un personnage à space five et quelque chose d'autre pourrait faire référence à foo, vous ne pouvez pas simplement le changer; vous devez copier toute la chaîne (bien sûr, une partie de cette fonctionnalité est abstraite en fonctions dans le véritable C sous-jacent, mais le point ici est de montrer le code qui est exécuté tout en un seul endroit).
struct String* concatenate(struct String* first, struct String* second)
{
struct String* new = malloc(sizeof(struct String));
new->length = first->length + second->length;
new->characters = malloc(new->length);
int i;
for(i = 0; i < first->length; i++)
new->characters[i] = first->characters[i];
for(; i - first->length < second->length; i++)
new->characters[i] = second->characters[i - first->length];
return new;
}
// The code that executes
struct String* astring;
char a = 'a';
astring->characters = &a;
astring->length = 1;
foo = concatenate(concatenate(slice(foo,0,4),astring),slice(foo,5,foo->length));
notez que concatenate est appelé deux fois ce qui signifie que toute la chaîne doit être bouclée! Comparez ceci au code C pour l'opération bar
:
bar->characters[4] = 'a';
l'opération de chaîne mutable est évidemment beaucoup plus rapide.
en Conclusion: dans la plupart des cas, vous voulez une chaîne immuable. Mais si vous avez besoin de faire beaucoup d'ajout et d'insertion dans une chaîne, vous avez besoin de la mutabilité pour la vitesse. Si vous voulez les avantages de sécurité de la simultanéité et de collecte des ordures avec elle, la clé est de garder vos objets mutables locale à une méthode:
// This will have awful performance if you don't use mutable strings
String join(String[] strings, String separator)
{
StringBuilder mutable;
boolean first = true;
for(int i = 0; i < strings.length; i++)
{
if(!first) first = false;
else mutable.append(separator);
mutable.append(strings[i]);
}
return mutable.toString();
}
puisque l'objet mutable
est une référence locale, vous n'avez pas à vous soucier sécurité de la concurrence (un seul fil le touche). Et comme il n'est référencé nulle part ailleurs, il n'est alloué que sur la pile, donc il est désallocé dès que l'appel de fonction est terminé (vous n'avez pas à vous soucier de la collecte des ordures). Et vous obtenez tous les avantages de performance à la fois la mutabilité et l'immutabilité.
en fait la chaîne N'est pas immuable si vous utilisez la définition de wikipedia suggérée ci-dessus.
L'état de la corde change la construction du poteau. Jetez un oeil à la méthode hashcode (). La chaîne cache la valeur du hashcode dans un champ local mais ne la calcule pas avant le premier appel de hashcode(). Cette évaluation paresseuse du hashcode place la chaîne dans une position intéressante en tant qu'objet immuable dont l'état change, mais on ne peut pas observer qu'elle ait changé sans utiliser la réflexion.
donc peut-être que la définition d'immuable devrait être un objet qui ne peut pas être observé avoir changé.
si l'état change dans un objet immuable après qu'il a été créé mais que personne ne peut le voir (sans réflexion) l'objet est-il encore immuable?
des objets Immuables sont des objets qui ne peuvent pas être modifiée par programmation. Ils sont particulièrement bons pour les environnements multi-threads ou d'autres environnements où plus d'un processus est capable de modifier (muter) les valeurs d'un objet.
juste pour clarifier, cependant, StringBuilder est en fait un objet mutable, pas un objet immuable. Une chaîne de caractères java régulière est immuable (ce qui signifie qu'une fois qu'elle a été créée, vous ne pouvez pas changer la chaîne de caractères sous-jacente sans changer la objet.)
par exemple, disons que j'ai une classe appelée ColoredString qui a une valeur String et une couleur String:
public class ColoredString {
private String color;
private String string;
public ColoredString(String color, String string) {
this.color = color;
this.string = string;
}
public String getColor() { return this.color; }
public String getString() { return this.string; }
public void setColor(String newColor) {
this.color = newColor;
}
}
dans cet exemple, la ColoredString est dite mutable parce que vous pouvez changer (muter) une de ses propriétés clés sans créer une nouvelle classe de ColoredString. La raison pour laquelle cela peut être mauvais est, par exemple, disons que vous avez une application GUI qui a plusieurs threads et vous utilisez ColoredStrings pour imprimer les données de la fenêtre. Si vous avez une instance de ColoredString qui a été créé comme
new ColoredString("Blue", "This is a blue string!");
alors on s'attendrait à ce que la chaîne soit toujours "bleue". Si un autre fil, cependant, s'est emparé de cette instance et a appelé
blueString.setColor("Red");
vous auriez soudainement, et probablement de façon inattendue, maintenant une corde" rouge "quand vous vouliez une" bleue". Pour cette raison, les objets immuables sont presque toujours préférés lorsque l'on passe des instances d'objets autour. Lorsque vous avez un cas où les objets mutables sont vraiment nécessaires, alors vous garderez typiquement l'objet en ne transmettant que des copies de votre champ de contrôle spécifique.
pour récapituler, en Java, java.lang.String est un objet immuable (il ne peut pas être modifié une fois qu'il est créé) et java.lang.StringBuilder est un objet mutable car il peut être modifié sans créer une nouvelle instance.
- dans les grandes applications, il est courant que la littérature à cordes occupe de grandes parties de la mémoire. Ainsi, pour gérer efficacement la mémoire, la JVM alloue une zone appelée "string constant pool".( noter que dans la mémoire même une chaîne non référencée porte autour d'un char[], un int pour sa longueur, et un autre pour son hashCode. Pour un nombre, par contre, un maximum de huit octets immédiats est requis )
- quand complier croise une corde littéral, il vérifie la piscine pour voir si il y a un identique littérale déjà présents. Et si l'on en trouve un, la référence à la nouvelle littérale est dirigée vers la chaîne existante, et aucune nouvelle 'chaîne objet littéral' n'est créée(la chaîne existante obtient simplement une référence supplémentaire).
- D'où: la mutabilité des chaînes de caractères sauve la mémoire...
- mais quand l'une des variables change de valeur, en fait - il est seulement leur référence qui a changé, pas la valeur en mémoire (donc elle n'affectera pas les autres variables qui s'y réfèrent) comme vu ci-dessous....
String s1 = "Vieux de la chaîne";
//s1 variable, refers to string in memory
reference | MEMORY |
variables | |
[s1] --------------->| "Old String" |
chaîne s2 = s1;
//s2 refers to same string as s1
| |
[s1] --------------->| "Old String" |
[s2] ------------------------^
s1 = "Nouvelle Chaîne";
//s1 deletes reference to old string and points to the newly created one
[s1] -----|--------->| "New String" |
| | |
|~~~~~~~~~X| "Old String" |
[s2] ------------------------^
La chaîne d'origine "en mémoire" n'a pas changé, mais la la variable de référence a été modifiée de sorte qu'elle se réfère à la nouvelle chaîne. Et si nous n'avions pas s2, "Old String" serait encore dans la mémoire mais nous ne serez pas en mesure d'y accéder...
"immuable" signifie que vous ne pouvez pas changer de valeur. Si vous avez une instance de classe String, n'importe quelle méthode que vous appelez et qui semble modifier la valeur, créera en fait une autre chaîne.
String foo = "Hello";
foo.substring(3);
<-- foo here still has the same value "Hello"
pour préserver les changements vous devriez faire quelque chose comme ceci foo = foo.sustring (3);
immuable vs mutable peut être drôle quand vous travaillez avec des collections. Pensez à ce qui va se passer si vous utilisez objet mutable comme une clé pour la carte et puis changer le valeur (astuce: pensez à equals
et hashCode
).
j'aime vraiment l'explication de SCJP Programmeur Certifié Sun pour Java 5 Guide d'Étude .
pour rendre Java plus efficace, la JVM réserve une zone spéciale de mémoire appelée "string constant pool"."Quand le compilateur rencontre une chaîne littérale, il vérifie la liste pour voir si une chaîne identique existe déjà. Si une correspondance est trouvée, la référence au nouveau littéral est dirigée vers la chaîne existante, et aucun nouvel objet littéral String n'est créé.
les objets immuables ne peuvent pas changer d'état après leur création.
il y a trois raisons principales pour utiliser des objets immuables chaque fois que vous le pouvez, Toutes qui aideront à réduire le nombre de bogues que vous introduisez dans votre code:
- il est beaucoup plus facile de raisonner sur le fonctionnement de votre programme quand vous savez que l'état d'un objet ne peut pas être modifié par une autre méthode
- objets immuables sont automatiquement thread safe (en supposant qu'ils sont publiés en toute sécurité) donc ne sera jamais la cause de ces bugs multithreading difficile à cerner
- les objets immuables auront toujours le même code de hachage, donc ils peuvent être utilisés comme les clés dans une HashMap (ou similaire). Si le code de hachage d'un élément d'une table de hachage devait changer, l'entrée de la table serait alors effectivement perdue, puisque les tentatives pour le trouver dans la table finiraient par chercher au mauvais endroit. C'est la principale raison qui Les objets String sont immuables - ils sont fréquemment utilisés comme des clés HashMap.
il y a aussi quelques autres optimisations que vous pourriez être en mesure de faire en code quand vous savez que l'état d'un objet est immuable - cacher le hachage calculé, par exemple - mais ce sont des optimisations et donc pas si intéressant.
de java.temps
il se peut qu'il soit un peu tard, mais pour comprendre ce qu'est un objet immuable, considérez l'exemple suivant de la nouvelle API Java 8 Date and Time ( java.heure ). Comme vous le savez probablement tous les objets date de Java 8 sont immuable donc dans l'exemple suivant
LocalDate date = LocalDate.of(2014, 3, 18);
date.plusYears(2);
System.out.println(date);
sortie:
2014-03-18
cette impression la même année que la date initiale parce que le plusYears(2)
renvoie un nouvel objet de sorte que l'ancienne date est toujours inchangée parce que c'est un objet immuable. Une fois créé, vous ne pouvez plus le modifier et la variable date le pointe toujours.
ainsi, cet exemple de code devrait capturer et utiliser le nouvel objet instancié et retourné par cet appel à plusYears
.
LocalDate date = LocalDate.of(2014, 3, 18);
LocalDate dateAfterTwoYears = date.plusYears(2);
date.toString () ... 2014-03-18
dateafterwoyears.toString () ... 2016-03-18
un sens a à voir avec la façon dont la valeur est stockée dans l'ordinateur, pour une chaîne.net par exemple, cela signifie que la chaîne en mémoire ne peut pas être changée, quand vous pensez que vous la changez, vous créez en fait une nouvelle chaîne en mémoire et pointez la variable existante (qui est juste un pointeur vers la collection réelle de caractères ailleurs) vers la nouvelle chaîne.
une fois instancié, ne peut pas être modifié. Considérez une classe qu'une instance de pourrait être utilisée comme clé pour un hashtable ou similaire. Consultez les pratiques exemplaires de Java.
immuable signifie qu'une fois l'objet créé, aucun de ses membres ne changera. String
est immuable car vous ne pouvez pas changer son contenu.
Par exemple:
String s1 = " abc ";
String s2 = s1.trim();
dans le code ci-dessus, la chaîne de caractères s1 n'a pas changé, un autre objet ( s2
) a été créé en utilisant s1
.
Qu'est-ce qu'un objet immuable ?
selon la Documentation de référence Java, "Un objet est considéré comme immuable si son état ne peut changer après sa construction" Simplement un immuable classe est une classe dont les propriétés ne peuvent pas être modifiées après la création. Cela signifie qu'à la création, toutes les données de l'instance sont fournies et restent inchangées jusqu'à la destruction des objets.
Pourquoi Des Objets Immuables ?
classes immuables sont grands pour les applications concurrentes. Comme par leur nature immuable, ils aident à maintenir l'application dans un comportement non corrompu et cohérent car l'état des instances ne peut pas être changé.
Préoccupations
les classes immuables sont faciles à concevoir, développer et utiliser car elles sont plus résistantes aux erreurs et plus sûres en raison de l'immuabilité. Cependant les programmeurs hésitent pour les utiliser en raison de la limitation de réutilisation. De plus, elle peut avoir un impact sur la création d'un objet plutôt que sur sa réutilisation. Toutefois, avec les compilateurs les plus sophistiqués, le coût de création est minime. En outre, les capacités fournies et l'avantage de l'immutabilité peuvent être adoptés au-delà de la réutilisation selon les besoins.
Comment cette Chaîne à ajouter ?
Nouvel objet String est créé avec la valeur donnée et la référence est mise à jour à la nouvelle instance isolant l'ancien objet.
référence: http://www.devdummy.com/2017/09/immutable-objects-in-java.html
String s1="Hi";
String s2=s1;
s1="Bye";
System.out.println(s2); //Hi (if String was mutable output would be: Bye)
System.out.println(s1); //Bye
s1="Hi"
: un objet s1
a été créé avec une valeur "Hi".
s2=s1
: un objet s2
est créé en référence à l'objet s1.
s1="Bye"
: l'ancienne s1
valeur de l'objet ne change pas parce que s1
a le type de chaîne et le type de chaîne est un type immuable, au lieu de cela le compilateur crée un nouvel objet de chaîne avec la valeur "Bye" et s1
référencé à lui. ici lorsque nous imprimons la valeur s2
, le résultat sera "Hi" pas "Bye" parce que s2
référencé à l'objet précédent s1
qui avait la valeur "Hi".
immuable signifie immuable ou non modifiable. Une fois que l'objet string est créé, ses données ou son état ne peuvent pas être changés
Envisager soufflet exemple,
class Testimmutablestring{
public static void main(String args[]){
String s="Future";
s.concat(" World");//concat() method appends the string at the end
System.out.println(s);//will print Future because strings are immutable objects
}
}
Let's get idée compte tenu soufflet diagramme,
dans ce diagramme, vous pouvez voir un nouvel objet créé en tant que"Monde Futur". Mais pas changer "futur". Because String is immutable
. s
, toujours parler de "futur". Si vous avez besoin d'appeler "futur monde",
String s="Future";
s=s.concat(" World");
System.out.println(s);//print Future World
pourquoi les objets string sont-ils immuables en java?
parce que Java utilise le concept de chaîne littérale. Supposons qu'il y ait 5 variables de référence, toutes se réfèrent à un objet "futur".Si une variable de référence change la valeur de l'objet, elle sera affectée à toutes les variables de référence. C'est pourquoi la chaîne des objets immuables Java.
Objets Immuables
un objet est considéré comme immuable si son état ne peut changer après sa construction. La confiance maximale sur les objets immuables est largement acceptée comme une stratégie saine pour créer du code simple et fiable.
les objets immuables sont particulièrement utiles dans les applications concurrentes. Puisqu'ils ne peuvent pas changer d'état, ils ne peuvent pas être corrompus par l'interférence de fil ou observés dans un état incohérent.
les programmeurs sont souvent réticents à employer des objets immuables, parce qu'ils s'inquiètent du coût de la création d'un nouvel objet par opposition à la mise à jour d'un objet en place. L'impact de la création d'un objet est souvent surestimé et peut être compensé par certains gains d'efficacité associés aux objets immuables. Il s'agit notamment de la réduction des frais généraux en raison de la collecte des ordures, et l'élimination du code nécessaire pour protéger les objets mutables contre la corruption.
le sous-sections suivantes de prendre une classe dont les instances sont mutables et dérive une classe immuable instances. Ce faisant, ils donnent des règles générales pour ce genre de conversion et démontrent certains des avantages des objets immuables.
un objet est considéré comme immuable si son état ne peut pas changer après qu'il est construit. La confiance maximale sur les objets immuables est largement accepté comme une bonne stratégie pour créer un code simple et fiable.
les objets immuables sont particulièrement utiles dans les applications concurrentes. Comme ils ne peuvent pas changer d'état, ils ne peuvent pas être corrompus par fil l'interférence observée ou dans un état incohérent.
j'aime cette phrase de la post
immuable objects ease competiency programming
un objet immuable est celui que vous ne pouvez pas modifier après l'avoir créé. Un exemple typique est la littérale des cordes.
et le langage de programmation, qui devient de plus en plus populaire, a une notion d '" immutabilité "à travers le mot-clé" invariant". Regardez cet article du Dr Dobb à ce sujet - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29 . Cela explique parfaitement le problème.