Classe immuable?
Comment peut-on rendre une classe Java immuable, Quel est le besoin d'immuabilité et y a-t-il un avantage à l'utiliser?
9 réponses
Qu'est Ce qu'un objet immuable?
Un objet immuable est un objet qui ne changera pas d'état après son instanciation.
Comment rendre un objet immuable?
En général, un objet immuable peut être créé en définissant une classe qui n'a aucun de ses membres exposés, et n'a aucun setters.
La classe suivante va créer un objet immuable:
class ImmutableInt {
private final int value;
public ImmutableInt(int i) {
value = i;
}
public int getValue() {
return value;
}
}
Comme on peut le voir dans l'exemple ci-dessus, la valeur du ImmutableInt
ne peut être défini que lorsque l'objet est instancié, et en n'ayant qu'un getter (getValue
), l'état de l'objet ne peut pas être modifié après instanciation.
Cependant, il faut veiller à ce que tous les objets référencés par l'objet doit être immuable, ou il pourrait être possible de changer l'état de l'objet.
Par exemple, autoriser une référence à un tableau ou ArrayList
à être obtenue via un getter permettra à l'état interne de changer en changeant le tableau ou recouvrement:
class NotQuiteImmutableList<T> {
private final List<T> list;
public NotQuiteImmutableList(List<T> list) {
// creates a new ArrayList and keeps a reference to it.
this.list = new ArrayList(list);
}
public List<T> getList() {
return list;
}
}
Le problème avec le code ci-dessus est, que le ArrayList
peut être obtenu par getList
et être manipulé, conduisant à l'état de l'objet lui-même à être modifié, donc, pas immuable.
// notQuiteImmutableList contains "a", "b", "c"
List<String> notQuiteImmutableList= new NotQuiteImmutableList(Arrays.asList("a", "b", "c"));
// now the list contains "a", "b", "c", "d" -- this list is mutable.
notQuiteImmutableList.getList().add("d");
Un moyen de contourner ce problème est de retourner une copie d'un tableau ou d'une collection, lorsqu'il est appelé à partir d'un getter:
public List<T> getList() {
// return a copy of the list so the internal state cannot be altered
return new ArrayList(list);
}
Quel est l'avantage de l'immuabilité?
L'avantage de l'immuabilité vient avec la concurrence. Il est difficile de maintenez l'exactitude dans les objets mutables, car plusieurs threads peuvent essayer de changer l'état du même objet, ce qui conduit certains threads à voir un état différent du même objet, en fonction du moment des lectures et des Écritures dans ledit objet.
En ayant un objet immuable, on peut s'assurer que tous les threads qui regardent l'objet verront le même état, car l'état d'un objet immuable ne changera pas.
En plus des réponses déjà données, je vous recommande de lire sur l'immuabilité dans Effective Java, 2e éd., car il y a quelques détails qui sont faciles à manquer (par exemple des copies défensives). De plus, Java efficace 2nd Ed. est un must-read pour chaque développeur Java.
L'immuabilité peut être obtenue principalement de deux façons:
- Utilisation des attributs d'instance
final
pour éviter la réaffectation - utiliser une interface de classe qui n'autorise tout simplement aucune opération capable de modifier ce qui se trouve dans votre classe (juste getters et non setters
Avantages de l'immuabilité sont les hypothèses que vous pouvez faire sur ces objets:
- vous gagnez la règle no-side effect (qui est vraiment populaire sur la programmation fonctionnelle langages) et vous permet d'utiliser plus facilement des objets dans un environnement concurrent, car vous savez qu'ils ne peuvent pas être modifiés de manière atomique ou non atomique lorsqu'ils sont utilisés par de nombreux threads
- les implémentations de langages peuvent traiter ces objets d'une manière différente, en les plaçant dans des zones de mémoire utilisées pour les données statiques, permettant une utilisation plus rapide et plus sûre de ces objets (c'est ce qui se passe dans la JVM pour les chaînes)
Vous faites une classe immuable comme ceci:
public final class Immutable
{
private final String name;
public Immutable(String name)
{
this.name = name;
}
public String getName() { return this.name; }
// No setter;
}
Les classes immuables sont utiles car elles sont sûres pour les threads. Ils expriment également quelque chose de profond sur votre conception: "ne peut pas changer cela."Lorsqu'il s'applique, c'est exactement ce dont vous avez besoin.
Q1) qu'est-ce qu'une classe et un objet immuables?
Ans) immuable class est une classe qui, une fois créée, son contenu ne peut pas être modifié. Les objets immuables sont les objets dont l'état ne peut pas être modifié une fois construits. par exemple classe de chaîne
Q2) Comment créer une classe immuable?
Ans) pour créer une classe immuable, les étapes suivantes doivent être suivies:
Créez une classe finale.
Définir les valeurs des propriétés utilisation du constructeur uniquement.
Faire les propriétés de la classe finale et privés
Ne fournissez aucun setters pour ces propriétés.
-
Si les champs d'instance contiennent des références à des objets mutables, autoriser la modification de ces objets:
Ne fournissez pas de méthodes qui modifient les objets mutables.
Ne partagez pas les références aux objets mutables. Ne jamais stocker les références vers des objets externes mutables transmis au constructeur; si nécessaire, créez des copies et stockez les références aux copies. De même, créer copies de vos objets mutables internes si nécessaire pour éviter retourner les originaux dans vos méthodes.
Les classes immuables ne peuvent pas réaffecter les valeurs après leur instanciation.Le constructeur attribue des valeurs à ses variables privées. Jusqu'à ce que l'objet devienne null, les valeurs ne peuvent pas être modifiées en raison de l'indisponibilité des méthodes setter.
Pour être immuable devrait satisfaire suivant,
- Al Les variables doivent être privées .
- Non mutateur méthodes(définition) sont fournis.
- évitez de surcharger la méthode en rendant la classe finale(forte immuabilité) ou des méthodes finale (semaine immuabilité).
- Cloner profondément s'il contient des classes non primitives ou mutables.
/**
* Strong immutability - by making class final
*/
public final class TestImmutablity {
// make the variables private
private String Name;
//assign value when the object created
public TestImmutablity(String name) {
this.Name = name;
}
//provide getters to access values
public String getName() {
return this.Name;
}
}
Advanteges: Les objets immuables contiennent ses valeurs initialisées jusqu'à ce qu'ils meurent.
Les classes immuables sont celles dont les objets ne peuvent pas être modifiés après la création.
Les classes immuables sont utiles pour
- but de la mise en cache
Simultanées De L'Environnement(Thread-Safe)
Dur pour l'Héritage
- la valeur ne peut être modifiée dans aucun environnement
Exemple
Classe De Chaîne
Exemple De Code
public final class Student {
private final String name;
private final String rollNumber;
public Student(String name, String rollNumber) {
this.name = name;
this.rollNumber = rollNumber;
}
public String getName() {
return this.name;
}
public String getRollNumber() {
return this.rollNumber;
}
}
Une autre façon de créer un objet immuable est d'utiliser Immutables.org Bibliothèque:
En supposant que les dépendances requises ont été ajoutées, créez un résumé classe avec des méthodes d'accesseur abstraites. Vous pouvez faire de même en annoter avec des interfaces ou même des annotations (@interface):
package info.sample;
import java.util.List;
import java.util.Set;
import org.immutables.value.Value;
@Value.Immutable
public abstract class FoobarValue {
public abstract int foo();
public abstract String bar();
public abstract List<Integer> buz();
public abstract Set<Long> crux();
}
Il est maintenant possible de générer puis d'utiliser l'immuable généré mise en œuvre:
package info.sample;
import java.util.List;
public class FoobarValueMain {
public static void main(String... args) {
FoobarValue value = ImmutableFoobarValue.builder()
.foo(2)
.bar("Bar")
.addBuz(1, 3, 4)
.build(); // FoobarValue{foo=2, bar=Bar, buz=[1, 3, 4], crux={}}
int foo = value.foo(); // 2
List<Integer> buz = value.buz(); // ImmutableList.of(1, 3, 4)
}
}
En tant que locuteur anglais non natif, je n'aime pas l'interprétation commune de "classe immuable" étant "les objets de classe construits sont immuables"; plutôt, je me penche pour interpréter cela comme "l'objet de classe lui-même est immuable".
Cela dit, "classe immuable" est une sorte d'objet immuable. La différence est en répondant à ce que l'avantage est. À ma connaissance / interprétation, la classe immuable empêche ses objets de modifier le comportement d'exécution.